# Memoria - METEC ## Análisis del sector informático en las islas El sector informático en las Islas Canarias es un sector en crecimiento y evolución constante. En los últimos años, ha experimentado un aumento en el número de empresas de tecnología y de startups, así como una mayor demanda de soluciones digitales en una variedad de industrias, como el turismo, la hostelería, las energías renovables, la salud, la educación y la industria del transporte. En cuanto a las empresas de software que existen en las Islas Canarias, estas van desde startups hasta grandes empresas establecidas. Algunas de las empresas más destacadas incluyen: **GMV Innovating Solutions**: una empresa dedicada a la ingeniería de software, sistemas y tecnologías de la información. Sus clientes incluyen empresas del sector aeroespacial y de defensa, así como empresas de transporte y logística. **Bee Ingenious**: una empresa de software que se enfoca en el desarrollo de aplicaciones móviles y soluciones de comercio electrónico para empresas en una variedad de industrias. **INERCO Tecnología**: una empresa de tecnología especializada en soluciones de gestión ambiental y energética para empresas de energías renovables, así como en tecnologías para el control y monitoreo de emisiones contaminantes. **ALTIA**: una empresa de tecnología que ofrece servicios de desarrollo de software, soluciones de inteligencia empresarial, servicios de consultoría y outsourcing de procesos de negocio. Sus clientes incluyen empresas del sector público, la banca y las finanzas, y la industria del turismo. En cuanto a las tecnologías que se utilizan en el sector informático en las Islas Canarias, estas incluyen lenguajes de programación como Java, Python, PHP y JavaScript, así como bases de datos como MySQL y Oracle. También hay una creciente adopción de tecnologías emergentes como la inteligencia artificial, el aprendizaje automático y la realidad virtual y aumentada. Los clientes potenciales para las empresas de software en las Islas Canarias son variados, incluyendo empresas de una amplia variedad de industrias, así como instituciones del sector público y organizaciones sin fines de lucro. Las empresas de tecnología también pueden trabajar con empresas fuera de las Islas Canarias, aprovechando su ubicación estratégica como punto de conexión entre Europa, África y América Latina. En resumen, el sector informático en las Islas Canarias es un sector en crecimiento y evolución constante, con una variedad de empresas de software que ofrecen soluciones digitales a una amplia gama de industrias y clientes potenciales. Las tecnologías más comunes utilizadas incluyen lenguajes de programación como Java y Python, así como bases de datos como MySQL y Oracle. Las oportunidades de crecimiento y desarrollo en este sector son prometedoras, especialmente en áreas emergentes como la inteligencia artificial y la realidad virtual y aumentada. ## Introducción Título del Proyecto: **METEC** Autor: **Edvin Freyer Ortega** y **Miguel Medina Ramírez** Resumen: METEC es un proyecto sobre una e-commerce que busca crear una tienda en línea con el objetivo de vender productos relacionados con la tecnología. Este tipo de proyecto implica la integración de una serie de elementos clave, tales como una plataforma de comercio electrónico, un catálogo de productos, un sistema de registro e iniciar sesión, un carrito de productos etc... Temática: Teconología, Hardware, Moviles etc... ## Motivación La motivación principal detrás de este proyecto, es la creciente demanda de compras en línea en todo el mundo. Cada vez son más las personas que prefieren realizar sus compras desde la comodidad de su hogar, en lugar de tener que desplazarse a una tienda física. Además, con la pandemia del COVID-19, esta tendencia se ha acelerado aún más, ya que muchas de las personas que se resistían a hacer compras online, se vieron "presionados" a hacerlo para evitar las multitudes y minimizar la exposición al virus, trás eso, mucha gente ha empezado a confiar y ver que es totalmente seguro. Al crear una tienda en línea, tienes la oportunidad de llegar a una audiencia global y ofrecer tus productos a un mercado mucho más amplio que el que podrías alcanzar a través de una tienda física. Además, una tienda en línea te permite estar abierta las 24 horas del día, los 7 días de la semana, lo que significa que tus clientes pueden comprar en cualquier momento que les resulte conveniente. Además, un e-commerce te permite ahorrar en costos de alquiler de local comercial y otros gastos relacionados con una tienda física, lo que puede aumentar significativamente la rentabilidad de tu negocio. También te permite recopilar datos valiosos sobre tus clientes, lo que te ayuda a personalizar tu oferta y mejorar la experiencia de compra en línea. ## Análisis del mercado actual. Aplicaciones existentes que den los mismos servicios El mercado actual de e-commerce es altamente competitivo, con una amplia gama de aplicaciones existentes que ofrecen servicios similares. Algunas de las aplicaciones de e-commerce más populares incluyen: **Amazon**: Es la plataforma de e-commerce más grande del mundo, con una amplia selección de productos y servicios, así como una variedad de opciones de envío y pago. **eBay**: Es una plataforma de subastas en línea que se ha expandido para ofrecer una variedad de productos y servicios en todo el mundo. **Shopify**: Es una plataforma de comercio electrónico que permite a los usuarios crear su propia tienda en línea y vender productos y servicios en línea. **AliExpress**: Es una plataforma de comercio electrónico propiedad del gigante chino Alibaba, que ofrece una amplia selección de productos a precios bajos directamente desde los fabricantes. **Etsy**: Es una plataforma de e-commerce enfocada en la venta de productos artesanales y vintage de pequeños negocios. A pesar de la fuerte competencia, hay un gran potencial en el mercado de e-commerce debido al creciente número de consumidores que prefieren hacer sus compras en línea. En conclusión, el mercado actual de e-commerce es altamente competitivo y existen varias aplicaciones que ofrecen servicios similares. Sin embargo, el creciente número de consumidores que prefieren hacer sus compras en línea, han impulsado la demanda de compras en línea, lo que significa que hay una gran oportunidad para aquellos que buscan ingresar en este mercado. ## Objetivos generales y específicos del aplicativo que se desea desarrollar Objetivos generales: - Ofrecer una amplia selección de productos de tecnología y hardware para satisfacer las necesidades de los clientes. - Proporcionar una plataforma en línea fácil de usar que permita a los clientes navegar y comprar productos de manera rápida y sencilla. Objetivos específicos: - Desarrollar un catálogo en línea que permita a los clientes navegar y buscar productos por categoría, marca, precio, especificaciones técnicas, etc... ## Metodologías utilizadas en la planificación y control del tiempo. Nuestra metodología utilizada es incremental, por funcionalidades, hemos ido añadiendo funcionalidades y componentes poco a poco, a veces cada uno individualmente por su rama, y otras, en común. Las herramientas utilizadas para la implementación de esta metodología, se ha hecho uso de GitHub para la gestión de versiones de código y la planificación y seguimiento de las tareas asociadas al desarrollo del proyecto. Por otro lado, se ha utilizado Trello para la gestión visual de tareas y proyectos, así como para el seguimiento del progreso de los mismos. Estas herramientas han sido fundamentales en la planificación y control del tiempo del proyecto de e-commerce, permitiendo una gestión eficiente y organizada de las tareas y recursos disponibles. ## Tecnologías y herramientas utilizadas en el proyecto El proyecto ha sido desarrollado utilizando una variedad de tecnologías y herramientas, entre las cuales se incluyen: **React:** una biblioteca de JavaScript utilizada para construir interfaces de usuario interactivas y dinámicas. **Firebase**: una plataforma de desarrollo de aplicaciones móviles y web que proporciona una amplia variedad de servicios, como alojamiento web, autenticación de usuarios, base de datos en tiempo real, almacenamiento en la nube, mensajería en la nube y analíticas. **Vite**: un build tool de desarrollo web que se enfoca en la velocidad y la simplicidad, y que ofrece un entorno de desarrollo rápido y eficiente para aplicaciones de una sola página (SPA) y sitios web estáticos. **Tailwind**: un framework de diseño de CSS utilizado para crear diseños responsivos y personalizados de manera rápida y sencilla. **Material Tailwind**: una biblioteca de componentes de interfaz de usuario para React, que ofrece una amplia variedad de componentes preconstruidos y personalizables para ayudar a los desarrolladores a crear aplicaciones atractivas y coherentes. **DaisyUI**: una biblioteca de componentes de interfaz de usuario (UI) para Tailwind CSS, que facilita la creación de diseños atractivos y personalizables. **UUID**: una biblioteca de generación de identificadores únicos (UUID) para JavaScript, que proporciona una manera fácil y confiable de crear identificadores únicos para objetos, elementos de la base de datos, etc. ## Estimación de recursos y planificación En este proyecto, la estimación de recursos y la planificación fueron tareas fundamentales para asegurar el éxito del proyecto. Se identificaron los recursos necesarios, como el tiempo y los conocimientos de los integrantes del equipo, y se hizo una estimación realista de los mismos. Con base en esta estimación, se planificó el proyecto de manera detallada, estableciendo objetivos y metas claras y un calendario para su realización. Se consideraron aspectos como la complejidad de la plataforma de e-commerce, la cantidad de productos que se venderían y el volumen de tráfico que se esperaba en el sitio web. Además, se llevó a cabo una gestión del riesgo para estar preparados para posibles obstáculos y desviaciones del plan. En resumen, la estimación de recursos y la planificación fueron elementos críticos para garantizar el éxito del proyecto de e-commerce, a pesar de no contar con personal adicional ni materiales o presupuesto. La estimación realista de los recursos disponibles permitió planificar de manera detallada y establecer objetivos alcanzables en el tiempo previsto. ## Mockups, prototipos, bosquejos Este fue nuestro prototipo inicial: ![](https://hackmd.io/_uploads/HkT8LdoN2.png) ## Análisis y diseño del proyecto Para el diseño de este proyecto, nos hemos decantado por un diseño minimalista, optando por usar colores como blanco y negro, para dar un toque profesional y de sencillez, ya que al usar distintos colores, podría dar al cliente una sensación de poca seriedad. Para la imagen de la empresa, hemos utilizado la imagen de un robot llamado Blitz. Hemos optado por esto, ya que nos parece una idea muy acertada, ya que esto hace que la página sea más user-friendly y, además, como indirectamente los robots e IA están relacionados con el mundo del software y el hardware, es una excelente elección, ya que al ser un tema que está en auge, da una impresión de modernidad. Para representarnos de cara al público, hemos decidido utilizar avatares similares a nosotros para tener un trato cercano con el cliente, más amigable y generar confianza. Para las páginas estáticas, hemos decidido poner un fondo dinámico relacionado con el espacio, ya que nos ha parecido una forma más amigable de acercar al usuario a la página y de unir la temática de robot/tecnología con el espacio. [Link del despliegue](https://test-metec-3.web.app/) ## Despliegue del aplicativo En el proceso de desarrollo del proyecto de e-commerce, el despliegue del aplicativo fue una tarea crítica que permitió que la plataforma estuviera disponible en línea para los usuarios finales. Para ello, se eligió un proveedor de alojamiento web que cumpliera con los requerimientos técnicos y de seguridad necesarios para la plataforma. Se configuraron los servidores, se implementaron las funcionalidades necesarias y se realizaron las pruebas correspondientes para asegurar que el sitio web funcionara correctamente. Se establecieron medidas de seguridad, como el uso de certificados SSL y la protección contra ataques DDoS, para garantizar la integridad y la privacidad de los datos de los usuarios y la seguridad de la plataforma en general. ## Documentación [Link a la documentación](https://github.com/Edvintrabajo/metec-ecommerce) ## Trayectoria del proyecto Conforme ha ido avanzando el proyecto hemos ido desarrollando hemos implementando diversas ramas para el avanze de nuestro proyecto. ![](https://hackmd.io/_uploads/ryzZDhkS3.png) La implementación de estas no fue complicada, tuvimos algun que otro conflicto con los merges, pero nada que no se puediera solucionar. El "golpe" más duro del proyecto fue a finales del primer mes del proyecto, aproximadamente el 20 de Abril, estando conformes con el desarrollo del proyecto pero no con el nuestro, decidimos cambiar las tecnologias que usabamos. La primera razón por la que decidimos cambiar de tecnologias es porque sentiamos que no estabamos aprendiendo nada y la razón principal de este proyecto es enfrentarte a una situación real. Simplemente repitienedo el mismo proceso que habiamos hecho con los anteriores proyectos no ibamos a aprender nada. La segunda razón fue como un reto, el tener que enfrentarte a tecnologias en poco tiempo y sacar un proyecto adelante con una fecha limite, ya que esta situación suele ser muy común en el desarrollo de proyectos, empezar utilizando una tecnología y acabar usando otra totalmente distinta, con plazos de entragas cortos. Como propuesta de cambio a esto propusimos cambiar nuestas tecnologias back-end, pasamos de usar Express a Firebase, ya habiamos oido hablar de esta tecnología y consideramos que merecía la pena intentar probarla debido a sus grandes características e implementaciones que ofrece. ![](https://hackmd.io/_uploads/HkT8ihJH2.png) El aprendizaje de Firebase no fue muy complejo, la documentación e infromación que buscamos fue de gran ayuda y nos permitio avanzar a pasos agigantados, practicamente recuperamos el mes perdido de trabajo en poco más de medio mes. No nos arrepentimos para nada haber cambiado de tecnologias ya que esta nos ha abierto otro mundo totalmente nuevo, el cual nos servira de referencia para futuros proyectos. ![](https://hackmd.io/_uploads/SJZa2h1B2.png) La rama de express esta disponible en nuestro repositorio ( Obviamente sin terminar ) ## Firebase Firebase es una plataforma digital diseñada para facilitar el desarrollo de aplicaciones web. Esta resulta extremadamente util para el desarrollo back-end de las aplicaciones gracias a sus modulos y validaciones. Comenzamos una vez tenemos ley Key de nuestro proyecto y firebase instalado previamente. ![](https://hackmd.io/_uploads/Hym6Zkern.png) Usamos la función IniatailizeApp con nuestra Key para iniciar nuestra app. Con esto hemos enlazado ya nuestro proyecto con firebase, hay muchas configuraciones que podemos realizar a partir de este punto. Para este proyecto hemos elegido: * auth * firestore * storage Antes de continuar vamos a explicar la función de estos 3 modulos. > **auth** > Este modulo nos permite gestionar todo lo relacionado con los usuarios: > - Inicio > - Registro > - Gestión > **firestore** > Actuaría como la base de datos general, aqui podemos crear, borrar, leer y modificar todos los datos que queramos y establcer todos los permisos que deseemos. > Por otro lado firestore es muy utíl para especificar dichos permisos, un ejemplo es el de poder dividir el permiso de escritura, este se puede subdividir en tres: > - Create > - Delete > - Update > > Pero aqui no acaba la cosa, porque gracias al auth podemos validar aun más permisos, con los que podemos verificar que para que se realize alguna request de escritura o lectura, el usuario deba estar loggeado o deba ser un admin, etc. Esto crea un gran abanico de posibilidades para las configuraciones. > **Storage** > El storage es usado para almacenar archivos binarios, esto resulta muy utíl y sencillo de usar a la hora de guardar o cunsuir imagenes. Cada uno de estos a de configurarse en firebase para permitir lectura y escritura, por ejemplo para firestore le dimos permisos de lectura a todos los usuarios, ya que todos nuestros usuarios pueden ver los productos sin estar logeados, pero escritura solo a los loggeados. ![](https://hackmd.io/_uploads/HkwiN1grh.png) Respectivamente sus funciones Getters, permiten acceder a sus respectivos datos. Por último vemos el googleProvider este nos permitira validar a los usuarios que inicien sesión con google. ### Firebase Dashboard Firebase cuenta con su propio dashboard para gestionar toda la información que desees. En este ejemplo mostramos a los usuarios con su datos pixelados. ![](https://hackmd.io/_uploads/rkOMuJeB2.png) ![](https://hackmd.io/_uploads/rkIROylSn.png) De igual manera nos encontramos con paneles de administración similares en el storage y en el firestore. ## Functions - Controllers ### Register En este punto nos encontramos con la función signUp la cual se encarga de crear los usuarios con la función createUserWithEmailAndPassword de firestore, este recibe el auth y los datos del usuario, si todo sale correcto creara un usuario en la base de datos; Como extra añadimos la función sendEmailVerification, que envía una verificaión a tu correo electrónico para verficiar que eres tu. Por último realiza un logOut ya que al crear un usuario, auqnue este no este verificado se guarda su status en el auth y si intentara ir a la pagina principal aparecería como logged. Por último en caso de error se te mostrara por pantalla. ![](https://hackmd.io/_uploads/S1GxbxxHh.png) ### Login Ahora pasamos con el signIn, la cual nos permite acceder a la pagina principal loggeados. Su funcionamiento es básico, verifica que el usuario existe y que este verificado. ![](https://hackmd.io/_uploads/r1BzXllS3.png) ¿Por que se realiza un reload del user? Por una sencilla razón, si el usuario verifica el usuario y vuelve a la página de antes, el auth no contemplara el estado de la verificación, al ejecutar un reload, contemplamos este caso. Por último al igual que en la función de registro, en caso de error se te mostrara por pantalla. ![](https://hackmd.io/_uploads/ryF2zelSh.png) ### Sign in with Google Esta función de firebase genera una ventana emergente la cual te permite elegir el usuario con el que te registraras en la web. Por último nos encargamos de redirigir a la página principal si todo va bien. ![](https://hackmd.io/_uploads/HkkvNgeB2.png) ### Sign out Esta ha sido la función más fácil de todas, ya que simplemente hay que pasarle el auth y se encargara de cerrar la cesión. ![](https://hackmd.io/_uploads/HJY3NgeH2.png) ### State User Data Esta función la hemos usado para manejar los datos del usuario en estados, el prefijo simplemente ha sido para poder reciclar la función tanto en el login como en el register. ![](https://hackmd.io/_uploads/ryMhHglS3.png) ### Product collection Vamos a empezar con las colecciones, las colecciones serían equivalente a las tablas en SQL, en este caso la de producto. La función collection recibe una base de datos y la referencia a su tabla. En este caso hacemos referencia a la base de datos de la configuración y la tabla products ![](https://hackmd.io/_uploads/ryCjUxgHh.png) ### Get Products Con la función query de firebase podemos preparar querys, ( esto sería parecido a los placehalders de PHP ) es un preparador de querys. La función getDocs simplemente ejecuta la query realizando un fetch. Filterdata filtra los datos mapeandolos, añadiendo un id junto con su información. Por último con los dos states de setProducts y setCurrentTenProducts son los que se encargan de guardar todos los productos y de guardar los 12 primeros respectivamente. ![](https://hackmd.io/_uploads/H16HIllHn.png) ### Get Trending Top Los productos trending top son aquellos con mayor nivel de raiting. Como en la anterior función ejecutamos preparamos una query, pero esta vez nos encontramos con dos funciones nuevas. **where =** Su función es filtrar los datos, recibe 3 parametros: - Parametro del producto (Element) - Condición (Condition) - Parametro en el que se cumple (Param) **orderBy =** Su función es ordenar el resultado de la query: - Parametro del producto (Element) - Orden (Order asc/desc) Por último al igual que en la función de get products filtramos nuevamente los datos. ![](https://hackmd.io/_uploads/rk0Hv-xr3.png) ### Get Product by Category Esta función es similar a la de trending top con la diferencia que ahora filtramos por categoria, en nuestro caso tenemos 6 tipos de cateogria: - Componentes - Ordenadores - Smartphone - Tablet - TVs - Perifericos Por último al igual que en la función de get products filtramos nuevamente los datos. ![](https://hackmd.io/_uploads/SkULK-gH3.png) ### Add Product Esta función se encarga de añadir los productos a nuestra base dedatos en firestore. La función getData simplemente recoge los datos del formulario. ImageRefName es un id para la imagen, ya que no podemos permitirnos que los ids coincidan. La función v4 es de un modulo llamado uuid, basicamente es un randomizador de caracteres, otra practica muy común establecida para guardar este tipo de archivos es creando un objeto Date ya que este te guarda todo detalle de fecha convirtiendola en única. El imageRef es una referencia al storage ( ubicación donde guardaremos la imagen) y la función ref nos permite hacer referencia al sotrage, esto sería un "equivalente" a la función query, mientras que uploadBytes se encargaría de ejecutarlo, basicamente recibiendo la referencia y la imagen ( Archivo ). Por último la url ejecuta getDownloadURL, este función se encarga de obtener la url de la imagen que fue desplegada en el storage lista para ser consumida. Una vez completado esto ya tendriamos la imagen del producto desplegada, una vez desplegada pasamos a subir el producto con los datos de la imagen desplegada con la función addDoc. La función addDoc recibe 2 parametros: - Colección ( Reference ) - Objeto ( Object with data ) ¿Por qué guardamos el id de la imagen? Porque a la hora de editar el producto tambien tenemos que ser capaces de tener acceso a la imagen. Por último validamos todos los casos de acierto y en la parte final del código ( finally ) ejecutamos un get de los productos en función de la categoría actual, para obtner la lista actualizada. ![](https://hackmd.io/_uploads/ByQWc-lHh.png) ### Delete Product La función delete product es muy sencilla, simplemente usando la función doc podemos hacer referencia a un producto concreto. Los parametros de doc son - Base de datos - Tabla - Id Seguidamente ejecutamos la cunsulta con getDoc, que obtiene un único producto, hacemos referencia al sotrage como hicimos anteriormente para obtener el id de la imagen por ultimo con las funciones deleteObject y deleteDoc borrarmos imagen y producto respectivamente teniendo como parametro sus referencias. Como en la función anterior validamos todos los casos y actualizamos la lista de productos. ![](https://hackmd.io/_uploads/BJgvVmlBh.png) ### Edit product Nos encontramos con la función más compleja de todas, updateProduct, como su nobmre indica esta es la encargada de actualizar los productos. Como hicimos anteriormente en el delete, obtenemos la referencia del producto, usamos nuevamente la función getData para obtener los datos del formulario, pero esta vez con el prefijo edit, para hacer referencia a los parametros del formulario edit. Seguidamente realizamos una comparación para ver si cambiamos la imagen nueva o no en caso de no existir. En caso de no existir continuamos con la función updateDoc que acuta de manera similar al addDoc, recibiendo los mismos parametros, una referencia y un objeto. En caso de existir simplemente realizamos los mismos pasos que en el addProduct, subimos primeramente la imagen y luego subimos el producto con la referencia de la imagen y la url. Finalmente obtenemos los productos segun la categoria y reseteamos el formulario ![](https://hackmd.io/_uploads/By8UomlBh.png) ![](https://hackmd.io/_uploads/Hy8tsQlr3.png) ![](https://hackmd.io/_uploads/ry5hiXlS3.png) ### Next Entramos ahora con el paginador, para el paginador creamos la función next, la cual nos permite avanzar en el array de productos. Inicalizamos dataQuey ya que esta va a bariar en función de la categoría, seugidamente cogemos el último elemento del array de productos actual con la función last, evaluamos en que categoría estamos para en función de cual estemos ejecutar una query. Por último ejecutamos la query, la mapeamos para poder filtrarla y seteamos la nueva lista de productos emepezando despues del indice del ultimo producto de la anterior lista, y cogiendo como máximo el límite de productos por pagína + 1 ya que si no nos cogería uno menos, y finalmente validamos todos los casos y realizamos un scroolSmooth que basicamente es un función que realiza scroll hacia el principio de una forma user-friendly ![](https://hackmd.io/_uploads/B1BrhmeB3.png) ![](https://hackmd.io/_uploads/Bk_93QlH3.png) ### Prev La función Prev es similar a la de Next, con la difrencia que esta recibe el primer elemento del anterior array y esta corta el array el indice del producto - los productos por página + 1, de resto actua de la misma forma que Next. ![](https://hackmd.io/_uploads/rJtaAXgS3.png) ![](https://hackmd.io/_uploads/Byqyy4gB3.png) ### Get Orders Esta función se encarga de obtener los pedidos del carrito, estos pedidos se encuentran almacenadas en las cookies. Primero, se obtiene la cookie actual usando el objeto document.cookie y se almacena en la variable cookies. Luego, se divide la cadena de cookies en un array de cookies separando cada cookie con el carácter ; y un espacio en blanco usando el método split('; '), y se almacena en la variable cookiesArray. Después, se busca en el array de cookies la cookie que comienza con el texto "orders=" utilizando el método find(), y se almacena en la variable ordersCookie. Si la cookie "orders" no existe, la función retorna un array vacío. Si la cookie "orders" existe, se obtiene el valor de la cookie, que es una cadena de texto que contiene la información de los pedidos, utilizando el método split('orders=')[1] que divide la cadena de la cookie en un array utilizando "orders=" como separador y devuelve el segundo elemento del array que es la cadena de texto que contiene la información de los pedidos. Se decodifica la cadena de texto con decodeURIComponent() y se convierte en un objeto JavaScript utilizando JSON.parse(), y se almacena en la variable orders. Finalmente, la función retorna el objeto orders. ![](https://hackmd.io/_uploads/S13trbeS3.png) ### Set Orders Esta función se encarga de agregar productos a la cookie de pedidos existente. Primero, se llama a la función getOrders() para obtener el objeto de pedidos actual de la cookie. Luego, se llama a la función checkOrder() para verificar si el producto que se quiere agregar ya existe en la lista de pedidos y obtener su índice. Si el producto nuevo no existe, checkOrder() devuelve -1. Si el producto no existe en la lista de pedidos, se agrega el nuevo pedido al final del objeto de pedidos con el método push(). Si el producto ya existe en la lista de pedidos, se actualiza la cantidad de unidades del pedido existente con la cantidad de unidades del nuevo pedido utilizando el operador +=. Después, se codifica la lista actualizada de pedidos con encodeURIComponent() y se convierte en una cadena de texto JSON utilizando JSON.stringify(), y se almacena en la variable encodedOrders. Finalmente, se actualiza la cookie de pedidos con el nuevo objeto de pedidos utilizando el método document.cookie, estableciendo el valor de la cookie como orders=${encodedOrders}, la duración máxima de la cookie en segundos como max-age=${30 * 24 * 60 * 60}, el alcance de la cookie en el sitio web como path=/, y la restricción de acceso a la cookie solo a través de solicitudes de mismo sitio (SameSite) como SameSite=Lax. ![](https://hackmd.io/_uploads/H1URIWlrh.png) ### Delete Order Esta función recibe un índice como parámetro que se refiere al índice de la orden que se desea eliminar. Luego, la función obtiene todas las órdenes almacenadas en una cookie utilizando la función getOrders. Después, la función utiliza el método splice para eliminar la orden correspondiente al índice que se proporciona como parámetro. El método splice cambia el contenido de un array al agregar o eliminar elementos en él. A continuación, la función utiliza encodeURIComponent y JSON.stringify para codificar la matriz de órdenes en una cadena y guardarla en la cookie. La función encodeURIComponent codifica una cadena en una versión válida de URI, mientras que JSON.stringify convierte un objeto JavaScript en una cadena JSON. Por último, la función actualiza la cookie orders con la nueva matriz de órdenes y establece la duración de la cookie en 30 días. Además, establece la ruta de la cookie como la raíz del sitio web (path=/) y define el atributo SameSite como Lax. El atributo SameSite es una medida de seguridad que ayuda a prevenir los ataques de CSRF (falsificación de solicitudes entre sitios). ![](https://hackmd.io/_uploads/SJxwvZgHn.png) ### Update Order Esta función recibe dos parámetros: index que se refiere al índice de la orden que se desea actualizar, y newOrder que es la nueva orden que se va a insertar en el índice especificado. La función primero obtiene todas las órdenes almacenadas en la cookie utilizando la función getOrders. Luego, la función actualiza la orden en el índice especificado con la nueva orden proporcionada a través del parámetro newOrder, utilizando la sintaxis de asignación de array. A continuación, la función utiliza encodeURIComponent y JSON.stringify para codificar la matriz de órdenes en una cadena y guardarla en la cookie. Por último, la función actualiza la cookie orders con la nueva matriz de órdenes y establece la duración de la cookie en 30 días. Además, establece la ruta de la cookie como la raíz del sitio web (path=/) y define el atributo SameSite como Lax. El atributo SameSite es una medida de seguridad que ayuda a prevenir los ataques de CSRF (falsificación de solicitudes entre sitios). ![](https://hackmd.io/_uploads/HyOx_ZxS2.png) ### Get Order Index Esta función recibe un parámetro id, que se refiere al ID de la orden que se está buscando. La función primero obtiene todas las órdenes almacenadas en la cookie utilizando la función getOrders. Luego, la función utiliza el método findIndex en la matriz de órdenes para encontrar el índice de la orden que tiene un ID que coincide con el ID proporcionado en el parámetro id. El método findIndex devuelve el índice del primer elemento en el array que satisface la función de prueba proporcionada. La función de prueba proporcionada a findIndex es una función de flecha que toma un objeto de orden y comprueba si su propiedad id es igual al ID proporcionado en el parámetro id. Si se encuentra una orden con el ID correspondiente, la función findIndex devuelve su índice en la matriz de órdenes. Si no se encuentra ninguna orden con el ID correspondiente, la función devuelve -1. Por último, la función devuelve el índice de la orden que se está buscando, o -1 si no se encuentra ninguna orden con el ID correspondiente. ![](https://hackmd.io/_uploads/BJMwdWxSn.png) ### Get Orders Count Esta función no recibe ningún parámetro. La función primero obtiene todas las órdenes almacenadas en la cookie utilizando la función getOrders. Luego, la función utiliza el método reduce en la matriz de órdenes para calcular la cantidad total de unidades en todas las órdenes. El método reduce toma dos argumentos: una función reductora y un valor inicial. La función reductora toma dos argumentos: un acumulador y el elemento actual del array. La función reductora se ejecuta en cada elemento del array, acumulando un valor mientras se recorre el array. En este caso, la función reductora suma el valor de la propiedad unidades de cada objeto de orden al acumulador, comenzando en 0. Al finalizar la iteración, el valor acumulado se convierte en la cantidad total de unidades en todas las órdenes. Por último, la función devuelve la cantidad total de unidades en todas las órdenes. ![](https://hackmd.io/_uploads/rJfa_-eH2.png) ### Get Total Orders Esta función calcula el total de dinero que hay en el carrito. Primero, se llama a la función "getOrders()" para obtener una lista de todos los pedidos realizados y se asigna esta lista a la constante "orders". Luego, se utiliza el método "reduce" de la lista "orders" para calcular el total de ventas. El método "reduce" aplica una función reductora a cada elemento de la lista y devuelve un valor acumulado. En este caso, la función reductora multiplica el número de unidades de cada pedido por el precio del mismo y lo suma al acumulador. Finalmente, la función devuelve el total de ventas calculado anteriormente. ![](https://hackmd.io/_uploads/SkjzK-xH2.png) ### Check Order Esta función toma un parámetro llamado idproducto. La función utiliza la función getOrders() para obtener una lista de todos los pedidos realizados y se asigna esta lista a la constante "orders". Luego, la función utiliza el método findIndex en la lista de órdenes para encontrar el índice de la primera orden que tenga un idproduct que coincida con el idproducto proporcionado como parámetro. Finalmente, la función devuelve el índice de la orden encontrada, que será un número entero que representa la posición de la orden en la lista de órdenes. Si no se encuentra ninguna orden con el idproduct proporcionado, la función devolverá -1. ![](https://hackmd.io/_uploads/Skm6tWxrn.png) ### Update Order Quantity Esta función toma dos argumentos: index y unidades. La variable index representa el índice del order que se quiere actualizar, mientras que unidades es la nueva cantidad de unidades a asignar. La función comienza obteniendo la información del carrito de compras actual mediante una llamada a la función "getOrders()". Luego, actualiza la cantidad de unidades para el pedido específico en la posición index del arreglo orders. Después, codifica el arreglo actualizado orders en un formato que pueda ser almacenado en una cookie utilizando encodeURIComponent(JSON.stringify(orders)). Finalmente, establece una cookie llamada "orders" con el valor codificado, que caduca en 30 días (30 * 24 * 60 * 60 segundos), tiene un alcance global de rutas (path="/"), y se establece en el valor de SameSite Lax para mejorar la seguridad de la cookie. ![](https://hackmd.io/_uploads/rkp89-lrh.png) ### Subtract Order Quantity Esta es una función que se encarga de restar una unidad de cantidad de un producto en el carrito. La función toma un parámetro "index", que representa la posición del producto en el array de objetos "orders". La función comienza obteniendo la información del carrito de compras actual mediante una llamada a la función "getOrders()". Luego, se resta una unidad a la propiedad "unidades" del objeto en la posición "index" de "orders". Esto se hace para actualizar la cantidad de unidades de un producto en el carrito. Finalmente, codifica el arreglo actualizado orders en un formato que pueda ser almacenado en una cookie utilizando encodeURIComponent(JSON.stringify(orders)). ![](https://hackmd.io/_uploads/B1pJi-eSh.png) ### Add Order Quantity Esta función toma un parámetro llamado "index". La función comienza obteniendo la información del carrito de compras actual mediante una llamada a la función "getOrders()". Incrementa en 1 la propiedad "unidades" del objeto de orden que se encuentra en el índice especificado por el parámetro "index". Codifica las órdenes actualizadas en formato JSON utilizando "JSON.stringify()" y luego codifica el resultado utilizando "encodeURIComponent()". Esto se hace para poder almacenar las órdenes en una cookie. Crea una cookie llamada "orders" y le asigna el valor de las órdenes codificadas en el paso anterior. La cookie tiene una duración máxima de 30 días ("max-age=${30 * 24 * 60 * 60}") y se establece en la raíz del sitio web ("path=/"). También se establece el atributo "SameSite" en "Lax" para aumentar la seguridad. ![](https://hackmd.io/_uploads/SkFRi-xH3.png) ### Clear Orders Esta función se encarga de limpiar todos los orders de las cookies. ![](https://hackmd.io/_uploads/HJZq2Zer3.png) ### Send Orders Esta es una función asíncrona que se utiliza para enviar los pedidos que están en las cookies al servidor y almacenarlos en una base de datos. Lo primero, obtenemos la información de los pedidos usando la función getOrders. Se comprueba si la longitud de la lista de pedidos es 0, la función se acaba, ya que si no existen pedidos no nos interesa enviar nada al servidor. Luego de hacer esta comprobación, creamos una variable fullDate que contiene la fecha y la hora actual en el formato "dd/mm/yyyy hh:mm", para saber cuando el cliente hace el pedido. Creamos una colección llamada "orders" en la base de datos. Convierte los objetos de orders en un array de productos, en donde se extraen los atributos "idproduct", "name", "unidades" y "price" de cada objeto de order, ya que son los únicos atributos que nos interesan. Luego convertimos este array de productos en un objeto JSON utilizando la función JSON.stringify. Creamos un objeto "cart" que contiene la información del pedido, incluyendo el identificador del usuario, el correo electrónico del usuario, el número total de productos en el pedido, el costo total del pedido, la fecha y hora actual, y la lista de productos en formato JSON. Finalmente, se ejecuta la función addDoc para agregar el objeto "cart" a la colección "orders" en la base de datos. Si la operación es exitosa, se borra la información de los pedidos utilizando la función clearOrders y muestra una alerta al usuario indicando que el pedido se realizó con éxito. Si la operación falla, muestra una alerta al usuario indicando el error. ![](https://hackmd.io/_uploads/Hk3nT-xSn.png) ![](https://hackmd.io/_uploads/HyyppbxSn.png) ## Pruebas Unitarias con Jest Las pruebas son una parte crucial en el desarrollo de cualquier proyecto de software. Nos permiten identificar y corregir errores antes de que lleguen a producción, lo que ahorra tiempo y recursos a largo plazo. En este apartado, vamos a explorar las pruebas que se han creado en tu proyecto, haciendo uso del framework Jest. Jest es una herramienta de pruebas muy popular entre los desarrolladores de JavaScript, ya que permite crear pruebas unitarias de manera sencilla y efectiva. Con Jest, se pueden probar componentes, funciones y cualquier otro tipo de código para garantizar que su funcionamiento sea el correcto. ![](https://hackmd.io/_uploads/H1w6UlxBh.png) En este apartado, vamos a enseñar algunos test de funciones que se han usado para el proyecto utilizando el framework Jest. Nos centraremos en lo que retorna las funciones. En la carpeta tests se encuentran los test hechos. Este es el contenido del archivo **isAdmin.test.js** ![](https://hackmd.io/_uploads/ByiUDgerh.png) Para hacer un test de una función, lo primero de todo es importar la función, luego utilizar la función 'describe' para agrupar conjuntos de pruebas relacionadas. Esta función permite organizar y estructurar las pruebas de manera jerárquica y lógica. Dentro de cada bloque, se pueden definir varias pruebas utilizando las funciones 'test' o 'it'. En el siguiente ejemplo, se usa la función 'test' para crear la primera prueba. En ella, se especifica el contexto de la prueba, que en este caso es comprobar si la función devuelve 'true' si el usuario que se le pasa es un administrador. Para ello, se crea una constante con un email que corresponde a un administrador y se ejecuta la función, guardando el resultado. Para comprobar el comportamiento esperado, se utiliza la función 'expect' en conjunto con 'toBe'. La función 'expect' se utiliza para definir lo que se espera que suceda en la prueba. Se crea una "expectativa" sobre el comportamiento de una parte específica del código que se está probando. Por su parte, 'toBe' es un método que se utiliza con 'expect' para comparar el resultado de una operación con un valor esperado. En el ejemplo, se espera que la función devuelva el valor 'true', por lo que se puede usar 'expect(func()).toBe(true)', siendo 'func()' la función que se está probando, en este caso 'isAdmin(email)'. Los otros dos tests son basicamente igual, en el segundo test, le pasamos un email que no es administrador, como en este comportamiento la función debería devolver 'false', lo único que cambia respecto al anterior test es el toBe a toBe(false). El tercer test, es el último comportamiento posible en esta función, donde se le pasa un email que es undefined, en este caso debería devolver false, por lo que el toBe vuelve a ser toBe(false). Para ejecutar esta batería de pruebas, debemos ejecutar este comando: ![](https://hackmd.io/_uploads/SkYtTlgS3.png) '--testPathPattern' Es una expresión regular que sirve para ejecutar los test que contengan ese patrón, porque si ejecutas 'npm run test', o 'npx jest', se ejecutan todos los test que tengas en el proyecto, y ahora solo queremos ejecutar los test de isAdmin en específico. La salida por pantalla debería ser así: ![](https://hackmd.io/_uploads/Hyru0xgSh.png) También hemos hecho tests para la función checkErrorCodes ![](https://hackmd.io/_uploads/Bk92AegB3.png) Con estos tests queremos comprobar que al pasarle un error code por parámetro en específico, no va a devolver el mensaje correcto. Un ejemplo sería: expect(checkErrorCodes('auth/invalid-email')).toBe('Email is not valid') A diferencia de los tests anteriores que solo devolvían valores booleanos, en este caso nos devuelve un resultado en específico. La salida debería ser: ![](https://hackmd.io/_uploads/BJ_pyWgH3.png) ## Conclusiones. En conclusión, el desarrollo de este proyecto de e-commerce fue un proceso desafiante, pero muy enriquecedor, que permitió a nuestro equipo adquirir una gran cantidad de conocimientos y habilidades. Durante el proceso, se llevó a cabo una planificación cuidadosa y se estimaron los recursos necesarios para garantizar el éxito del proyecto. Se implementaron funcionalidades importantes, como el registro e inicio de sesión, el carrito, el crud de los productos etc... Además, se establecieron medidas de seguridad para proteger la plataforma y los datos de los usuarios, y se realizaron pruebas rigurosas para garantizar su correcto funcionamiento. El despliegue de la plataforma en línea fue un proceso importante que permitió que la plataforma estuviera disponible para los usuarios finales. Se eligió un proveedor de alojamiento web seguro y se establecieron medidas de seguridad adicionales para proteger la plataforma y los datos de los usuarios. En resumen, este proyecto de e-commerce nos permitió aplicar los conocimientos adquiridos en clase, y nos dio la oportunidad de enfrentar desafíos importantes. Estamos satisfechos con el resultado final. ## Vías futuras de desarrollo. Algunas ideas que hemos tenido, que no hemos podido implementar por falta de tiempo son: **Pasarela de pago**: Una pasarela de pago te permitiría ofrecer a los usuarios una forma segura y confiable de pagar por tus productos o servicios directamente en la plataforma. Existen opciones como Stripe o PayPal para implementar esta funcionalidad. **Personalización de perfil**: La personalización de perfil es una forma de permitir que los usuarios de tu plataforma puedan expresar su identidad y preferencias. Puedes considerar opciones como permitir la carga de imágenes de perfil, la creación de biografías, la selección de temas de color, la configuración de notificaciones, entre otras. **Páginas para cada producto con comentarios y preguntas**: Las páginas de producto son una excelente forma de mostrar tus productos de manera detallada. Además, el que puedan dejar comentarios y preguntas en estas páginas sirve para crear un espacio interactivo y de retroalimentación. **Soporte en chat**: Ofrecer soporte en tiempo real a través de chat puede ayudar a resolver las dudas o problemas de tus usuarios de manera rápida y efectiva. Existen opciones como chatbots. **Lista de favoritos**: Permitir a los usuarios guardar productos en una lista de favoritos les facilitará encontrar y comprar sus productos preferidos de manera rápida. Además, también podrás recopilar información valiosa sobre las preferencias de los usuarios. **Historial de pedidos**: Un historial de pedidos permitirá a tus usuarios acceder a información sobre sus compras anteriores, incluyendo detalles sobre los productos o servicios comprados, fechas de compra y precios. Esto puede ser especialmente útil para usuarios que deseen repetir una compra o realizar un seguimiento de sus compras a lo largo del tiempo. **DashBoard**: Actualizar el dashbaord para mayor organización de los productos, orders y clientes, y no depender de firebase. **Filtro**: Actualizar el filtro para permiter filtrar productos, por marcas, precios, raiting ... ( user-friendly ) ### Exposición [Link de la exposición](https://www.canva.com/design/DAFi5GknQ-c/9AMy8ExTqvOJJLF67EIPVQ/edit?utm_content=DAFi5GknQ-c&utm_campaign=designshare&utm_medium=link2&utm_source=sharebutton) ## Bibliografía, webgrafía utilizada utilizada con enlace a los diferentes recursos. Durante el desarrollo de este proyecto, se han utilizado diversas fuentes de información que han sido de gran utilidad. A continuación, se presentan las principales referencias web utilizadas: - Documentación oficial de React: https://reactjs.org/docs/getting-started.html - Documentación oficial de Firebase: https://firebase.google.com/docs - Documentación oficial de Tailwind CSS: https://tailwindcss.com/docs - Documentación oficial de Node.js: https://nodejs.org/en/docs/ - Documentación oficial de Material Tailwind: https://www.material-tailwind.com/docs/react/installation Además, hemos aplicado muchos conocimientos aprendidos de los siguientes videos de Youtube: - Firebase Firestore CRUD de fazt: https://youtu.be/ey4k6mW9ds4 - Autenticación con Firebase de fazt: https://youtu.be/Djh_eVj0D2w - Curso de React de midudev: https://youtu.be/7iobxzd_2wY - Curso de Tailwind de midudev: https://youtu.be/h5HQVHTpeHs - Curso de Firebase de PedroTech: https://www.youtube.com/watch?v=2hR-uWjBAgw&ab_channel=PedroTech