diff --git a/README.md b/README.md index fe12fa3..327a6dd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Creando una Red Social +# MusiClub ## Índice @@ -17,8 +17,6 @@ Instagram, Snapchat, Twitter, Facebook, Twitch, Linkedin, etc. Las redes sociales han invadido nuestras vidas. Las amamos u odiamos, y muchos no podemos vivir sin ellas. -![adem-ay-Tk9m_HP4rgQ-unsplash](https://user-images.githubusercontent.com/110297/135544666-4efa54f1-4ff6-4c4c-b398-6df04ef56117.jpg) - Hay redes sociales de todo tipo y para todo tipo de intereses. Por ejemplo, en una ronda de financiamiento con inversionistas, se presentó una red social para químicos en la que los usuarios podían publicar artículos sobre sus @@ -26,40 +24,79 @@ investigaciones, comentar en los artículos de sus colegas, y filtrar artículos de acuerdo a determinadas etiquetas o su popularidad, lo más reciente, o lo más comentado. -## 2. Resumen del proyecto +## 2. Definición del proyecto 🤟 + +En este proyecto construimos una Red Social, siendo la música el tema principal -En este proyecto construirás una Red Social sobre lo que decidan tú y tu equipo. -Podría ser, por ejemplo, sobre alimentación saludable, feminismo, educación, -salud, energías renovables, amantes de las [Empanadas](https://es.wikipedia.org/wiki/Empanada) -o de los [Tacos de Canasta](https://es.wikipedia.org/wiki/Taco), -de la [Feijoada](https://es.wikipedia.org/wiki/Feijoada), o de lo que sea. +![../logo.png](https://github.com/Mitzymora/DEV008-social-network/blob/main/src/logo.png) -Tu Red Social tendrá que permitir a cualquier usuario crear una cuenta de acceso +Esta Red Social permite a cualquier usuario crear una cuenta de acceso y loguearse con ella; crear, editar, borrar y _"likear"_ publicacciones. -Por lo tanto, en este proyecto construirás una +En este proyecto construimos una [Single-page Application (SPA)](https://es.wikipedia.org/wiki/Single-page_application) -[_responsive_](https://curriculum.laboratoria.la/es/topics/css/02-responsive) (con más de una vista / página) -en la que podamos **leer y escribir datos**. +[_responsive_] (con más de una vista / página) +en la que podemos **leer y escribir datos**, misma que utiliza [_Firebase_] para la autenticación +de usuarios y hosting, tambien nos apoyamos de [_Firestore_] para la recopilación, sincronización +y almacenamiento de datos. + +Nuestra web tiene 4 componentes: +*Home, siendo la pantalla donde inicia la app y que te redirige a +los sitios para iniciar sesión o registrarte. +* +Register: Lugar en donde puedes registrarte usando algún nombre de usuario, correo y contraseña ó, si bien lo prefieres, puedes ingresar tu cuenta de google. + +Login: En este sitio puedes iniciar sesión con el correo y contraseña que anteriormente brindaste, al igual, +puedes ingresar desde tu cuenta de google. + +Feed: Permite visualizar y realizar los post, mismo que puedes editar las veces que quieras y/o eliminar en el momento que te sea necesario. + +![home](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/HomeImg.jpeg) +![login](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/Login.jpeg) +![register](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/register.jpeg) +![feed](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/feed.jpeg) + +## 3.Historias de Usuario + +Los principales usuarios del producto son personas de entre 20-35 años con acceso a internet que les interesa compartir sus canciones, bandas y conciertos favoritos y así poder encontrar otras personas que compartan sus mismos gustos. Para crear las [historias de usuario](https://docs.google.com/forms/d/1PxapQzWZxcf1TQtAI2VN7oFJomCufePqrjAG6rpTPq0/edit?usp=forms_home&ths=true) realizamos un formulario donde nos compartieron las facilidades accesibilidad y de diseño. + +![formulario](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/formulario.jpeg) +![HU](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/HU.jpg) + + +## 5.Organización -### Los objetivos generales de este proyecto son los siguientes +Para planificar nuestros horarios y avances, utilizamos Trello como herramienta. +Haciendo columnas para ubicar los faltantes y avances de las historias de usuarios, así como +de nuestros bloqueos para poder solicitar ayuda en momentos de bloqueos. + +![Trello](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/trello.jpeg) + + +## 6.Prototipos +Los prototipos de baja fidelidad de hicieron basados en las historias de usuario anteriores para así después trabajar con los prototipos de alta fidelidad y poder trabajar en su diseño una vez terminada la funcionabilidad de la página. + + +![prototipohandmade](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/prototipobaja.jpg) +![prototipobaja](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/prototipo%20baja.png) +![prototipo_registro](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/prototipo2alta.jpg) +![prototipo_login](https://github.com/Mitzymora/DEV008-social-network/blob/main/readme%20imagenes/prototipoalta.jpg) + +### Los objetivos generales de este proyecto fueron los siguientes * Desarrollar una SPA con temática de red social * Aplicar los conceptos de responsividad en el desarrollo de las vistas (templates) * Implementar un router para la navegación entre las diferentes vistas de la aplicación * Emplear un servicio externo para la persistencia de datos de la aplicación -* Crear una suite de pruebas unitarias que permitan testear código asíncrono -Para lograr estos objetivos, deberás aprender y hacer uso de las siguientes +Para lograr estos objetivos, aprendimos e hicimos uso de las siguientes herramientas o habilidades técnicas: -## 3. Objetivos de aprendizaje - -Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en tu proyecto. Piensa en eso al decidir tu estrategia de trabajo. +## 6. Objetivos de aprendizaje ### HTML -- [ ] **Uso de HTML semántico** +- [x] **Uso de HTML semántico**
Links

@@ -69,7 +106,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t ### CSS -- [ ] **Uso de selectores de CSS** +- [x] **Uso de selectores de CSS**

Links

@@ -77,7 +114,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [CSS Selectors - MDN](https://developer.mozilla.org/es/docs/Web/CSS/CSS_Selectors)

-- [ ] **Modelo de caja (box model): borde, margen, padding** +- [x] **Modelo de caja (box model): borde, margen, padding**
Links

@@ -88,7 +125,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [display - CSS Tricks](https://css-tricks.com/almanac/properties/d/display/)

-- [ ] **Uso de flexbox en CSS** +- [x] **Uso de flexbox en CSS**
Links

@@ -97,7 +134,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [Flexbox - MDN](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox)

-- [ ] **Uso de CSS Grid Layout** +- [x] **Uso de CSS Grid Layout**
Links

@@ -107,7 +144,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t ### Web APIs -- [ ] **Uso de selectores del DOM** +- [x] **Uso de selectores del DOM**

Links

@@ -116,7 +153,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [Localizando elementos DOM usando selectores - MDN](https://developer.mozilla.org/es/docs/Web/API/Document_object_model/Locating_DOM_elements_using_selectors)

-- [ ] **Manejo de eventos del DOM (listeners, propagación, delegación)** +- [x] **Manejo de eventos del DOM (listeners, propagación, delegación)**
Links

@@ -126,7 +163,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [El objeto Event](https://developer.mozilla.org/es/docs/Web/API/Event)

-- [ ] **Manipulación dinámica del DOM** +- [x] **Manipulación dinámica del DOM**
Links

@@ -138,7 +175,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [Node.textContent - MDN](https://developer.mozilla.org/es/docs/Web/API/Node/textContent)

-- [ ] **Ruteado (History API, evento hashchange, window.location)** +- [x] **Ruteado (History API, evento hashchange, window.location)**
Links

@@ -147,7 +184,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t ### JavaScript -- [ ] **Arrays (arreglos)** +- [x] **Arrays (arreglos)**

Links

@@ -160,16 +197,16 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [Array.prototype.reduce() - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)

-- [ ] **Objetos (key, value)** +- [x] **Objetos (key, value)**
Links

* [Objetos en JavaScript](https://curriculum.laboratoria.la/es/topics/javascript/05-objects/01-objects)

-- [ ] **Diferenciar entre tipos de datos primitivos y no primitivos** +- [x] **Diferenciar entre tipos de datos primitivos y no primitivos** -- [ ] **Variables (declaración, asignación, ámbito)** +- [x] **Variables (declaración, asignación, ámbito)**
Links

@@ -177,7 +214,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [Variables](https://curriculum.laboratoria.la/es/topics/javascript/01-basics/02-variables)

-- [ ] **Uso de condicionales (if-else, switch, operador ternario, lógica booleana)** +- [x] **Uso de condicionales (if-else, switch, operador ternario, lógica booleana)**
Links

@@ -185,7 +222,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [Tomando decisiones en tu código — condicionales - MDN](https://developer.mozilla.org/es/docs/Learn/JavaScript/Building_blocks/conditionals)

-- [ ] **Uso de bucles/ciclos (while, for, for..of)** +- [x] **Uso de bucles/ciclos (while, for, for..of)**
Links

@@ -193,7 +230,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [Bucles e iteración - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Loops_and_iteration)

-- [ ] **Funciones (params, args, return)** +- [x] **Funciones (params, args, return)**
Links

@@ -203,28 +240,8 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [Funciones — bloques de código reutilizables - MDN](https://developer.mozilla.org/es/docs/Learn/JavaScript/Building_blocks/Functions)

-- [ ] **Pruebas unitarias (unit tests)** -
Links

- - * [Empezando con Jest - Documentación oficial](https://jestjs.io/docs/es-ES/getting-started) -

- -- [ ] **Pruebas asíncronas** - -
Links

- - * [Tests de código asincrónico con Jest - Documentación oficial](https://jestjs.io/docs/es-ES/asynchronous) -

- -- [ ] **Uso de mocks y espías** - -
Links

- - * [Manual Mocks con Jest - Documentación oficial](https://jestjs.io/docs/es-ES/manual-mocks) -

- -- [ ] **Módulos de ECMAScript (ES Modules)** +- [x] **Módulos de ECMAScript (ES Modules)**
Links

@@ -232,20 +249,20 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [export - MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Statements/export)

-- [ ] **Uso de linter (ESLINT)** +- [x] **Uso de linter (ESLINT)** -- [ ] **Uso de identificadores descriptivos (Nomenclatura y Semántica)** +- [x] **Uso de identificadores descriptivos (Nomenclatura y Semántica)** -- [ ] **Diferenciar entre expresiones (expressions) y sentencias (statements)** +- [x] **Diferenciar entre expresiones (expressions) y sentencias (statements)** -- [ ] **Callbacks** +- [x] **Callbacks**
Links

* [Función Callback - MDN](https://developer.mozilla.org/es/docs/Glossary/Callback_function)

-- [ ] **Promesas** +- [x] **Promesas**
Links

@@ -255,48 +272,40 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t ### Control de Versiones (Git y GitHub) -- [ ] **Git: Instalación y configuración** +- [x] **Git: Instalación y configuración** -- [ ] **Git: Control de versiones con git (init, clone, add, commit, status, push, pull, remote)** +- [x] **Git: Control de versiones con git (init, clone, add, commit, status, push, pull, remote)** -- [ ] **Git: Integración de cambios entre ramas (branch, checkout, fetch, merge, reset, rebase, tag)** +- [x] **Git: Integración de cambios entre ramas (branch, checkout, fetch, merge, reset, rebase, tag)** -- [ ] **GitHub: Creación de cuenta y repos, configuración de llaves SSH** +- [x] **GitHub: Creación de cuenta y repos, configuración de llaves SSH** -- [ ] **GitHub: Despliegue con GitHub Pages** +- [x] **GitHub: Despliegue con GitHub Pages**

Links

* [Sitio oficial de GitHub Pages](https://pages.github.com/)

-- [ ] **GitHub: Colaboración en Github (branches | forks | pull requests | code review | tags)** +- [x] **GitHub: Colaboración en Github (branches | forks | pull requests | code review | tags)** -- [ ] **GitHub: Organización en Github (projects | issues | labels | milestones | releases)** +- [x] **GitHub: Organización en Github (projects | issues | labels | milestones | releases)** ### Centrado en el usuario -- [ ] **Diseñar y desarrollar un producto o servicio poniendo a las usuarias en el centro** +- [x] **Diseñar y desarrollar un producto o servicio poniendo a las usuarias en el centro** ### Diseño de producto -- [ ] **Crear prototipos de alta fidelidad que incluyan interacciones** +- [x] **Crear prototipos de alta fidelidad que incluyan interacciones** -- [ ] **Seguir los principios básicos de diseño visual** +- [x] **Seguir los principios básicos de diseño visual** ### Investigación -- [ ] **Planear y ejecutar testeos de usabilidad de prototipos en distintos niveles de fidelidad** - -
Links

- - * [Intro a testeos usabilidad](https://coda.io/@bootcamp-laboratoria/contenido-ux/test-de-usabilidad-15) - * [Pruebas con Usuarios 1 — ¿Qué, cuándo y para qué testeamos?](https://eugeniacasabona.medium.com/pruebas-con-usuarios-1-qu%C3%A9-cu%C3%A1ndo-y-para-qu%C3%A9-testeamos-7c3a89b4b5e7) -

- ### Firebase -- [ ] **Firebase Auth** +- [x] **Firebase Auth**
Links

@@ -304,7 +313,7 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [Administra usuarios en Firebase (onAuthStateChanged)](https://firebase.google.com/docs/auth/web/manage-users?hl=es#get_the_currently_signed-in_user)

-- [ ] **Firestore** +- [x] **Firestore**
Links

@@ -313,246 +322,3 @@ Reflexiona y luego marca los objetivos que has llegado a entender y aplicar en t * [Obtén actualizaciones en tiempo real con Cloud Firestore - Documentación oficial](https://firebase.google.com/docs/firestore/query-data/listen?hl=es)

-## 4. Consideraciones generales - -* Este proyecto se debe trabajar en equipos de tres. - -* El rango de tiempo estimado para completar el proyecto es de 4 a 5 Sprints. - -* La lógica del proyecto debe estar implementada completamente en JavaScript - (ES6+), HTML y CSS :smiley:. Para este proyecto **no está permitido** utilizar - _frameworks_ o librerías de CSS y JS. - -* La división y organización del trabajo debe permitir, sin excepciones, que - **cada integrante** del equipo practique el aprendizaje de todo lo involucrado - en **cada historia**. _No se dividan el trabajo como en una fábrica._ - - ¿Hasta acá has avanzado en tus proyectos con cierta fluidez y sin mayores - problemas? Sé generosa con tus compañeras, permíteles aprender y practicar - sin restricciones, aunque tome un poco más de tiempo. Aproveha de - _coachearlas_, de hacer _pair programming_, una de las mejores maneras de - aprender es explicando verbalmente. - - - ¿Se te está haciendo difícil y te cuesta un poco más avanzar? No te quedes - con las partes "fáciles" del proyecto, conversa, negocia, exige tu oportunidad - para practicar y aprender lo que se te hace más difícil. - -* Solamente pueden trabajar en una única historia por vez, no pueden avanzar a - la siguiente sin haber completado la anterior. La historia se completa cuando - se cumplen **todos** sus Criterios de Aceptación + **toda** su Definición - de Terminado. - -Para comenzar tendrás que hacer un _fork_ y _clonar_ este repositorio. - -## 5. Criterios de aceptación mínimos del proyecto - -### 5.1 Boilerplate - -Este proyecto no incluye un _boilerplate_ completo, solo algunos archivos de -configuración basico, así es que tendrás que definir la estructura de carpetas -y escribir tus propias Pruebas Unitarias (_tests_). Para hacerlo, puedes guiarte -de los proyectos anteriores y/o organizar los archivos siguiendo una estructura -de [Modelo-Vista-Controlador](https://developer.mozilla.org/es/docs/Glossary/MVC). - -En este proyecto vamos a usar una herramienta llamada -[Vite](https://es.vitejs.dev/) para empaquetar nuestros módulos y arrancar -el servidor de desarrollo, el cual provee nuestros archivos utilizando -la estrategia `Hot Module Replacement` -[(HMR)](https://es.vitejs.dev/guide/features.html#hot-module-replacement), -esto significa que cuando hagas cambios en los archivos que estén siendo -servidos, el navegador automáticamente se actualizará sin tener que refrescar -y volver a cargar todo el sitio. Debes tener especial cuidado de no tener -ninguna _dependencia circular_ en tu código ya que -[eso puede ocasionar problemas con HMR](https://es.vitejs.dev/guide/troubleshooting.html#ocurre-un-refresco-completo-en-lugar-de-hmr). -(`eslint-plugin-import` tiene una regla -[import/no-cycle](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-cycle.md) -que va a avisar si las tiene.) - -### 5.2 Definición del producto - -En el `README.md` cuéntanos brevemente cómo descubriste las necesidades de los -usuarios y cómo llegaste a la definición final de tu producto. Es importante -que detalles: - -* Quiénes son los principales usuarios de producto. -* Qué problema resuelve el producto / para qué le servirá a estos usuarios. - -### 5.3 Historias de usuario - -Una vez que entiendas las necesidades de tus usuarixs, escribe las Historias de -Usuario que representen todo lo que necesitan hacer/ver en la Red Social. Cada -una de tus Historias de Usuario debe tener: - -* **Criterios de Aceptación:** todo lo que debe ocurrir para satisfacer las - necesidades del usuario. - -* **Definición de terminado:** todos los aspectos técnicos que deben cumplirse - para que, como equipo, sepan que esa historia está terminada y lista - para publicarse. **Todas** tus Historias de Usuario (salvo excepciones), deben - incluir estos aspectos en su Definición de Terminado (más todo lo que - necesiten agregar): - - - Debe ser una SPA. - - Debe ser _responsive_. - - Deben haber recibido _code review_ de al menos una compañera de otro equipo. - - Hicieron los _test_ unitarios - - Testearon manualmente buscando errores e imperfecciones simples. - - Hicieron _pruebas_ de usabilidad e incorporaron el _feedback_ de los - usuarios como mejoras. - - Desplegaron su aplicación y etiquetaron la versión (git tag). - -### 5.4 Diseño de la Interfaz de Usuario (prototipo de baja fidelidad) - -Debes definir cuál será el flujo que seguirá el usuario dentro de tu aplicación -y, con eso, diseña la Interfaz de Usuario (UI por sus siglas en inglés) que -siga este flujo. - -### 5.5 Responsive - -Debe verse bien en dispositivos de pantallas grandes -(computadoras/es, laptops, etc.) y pequeñas (_tablets_, celulares, etc.). Te -sugerimos seguir la técnica de _`mobile first`_ (más detalles sobre esta técnica -al final). - -### 5.6 Consideraciones del comportamiento de la interfaz de usuario (UI) - -Estas consideraciones te ayudarán a escribir las Definiciones de Terminado de -tus H.U.: - -#### Creación de cuenta de usuario e inicio de sesión - -* _Login_ con Firebase: - - Para el _login_ y las publicaciones en el muro puedes utilizar [Firebase](https://firebase.google.com/products/database/) - - Creación de cuenta de acceso y autenticación con cuenta de correo y - contraseña, y también con una cuenta de Google. -* Validaciones: - - Solamente se permite el acceso a usuarios con cuentas válidas. - - No pueden haber usuarios repetidos. - - La cuenta de usuario debe ser un correo electrónico válido. - - Lo que se escriba en el campo (_input_) de contraseña debe ser secreto. -* Comportamiento: - - Al enviarse el formulario de registro o inicio de sesión, debe validarse. - - Si hay errores, se deben mostrar mensajes descriptivos para ayudar al - usuario a corregirlos. - -#### Muro/timeline - -* Validaciones: - - Al publicar, se debe validar que exista contenido en el _input_. -* Comportamiento: - - Al recargar la aplicación, se debe verificar si el usuario está _logueado_ - antes de mostrar contenido. - - Poder publicar un _post_. - - Poder dar y quitar _like_ a una publicación. Máximo uno por usuario. - - Llevar un conteo de los _likes_. - - Poder eliminar un post específico. - - Pedir confirmación antes de eliminar un _post_. - - Al dar _click_ para editar un _post_, debe cambiar el texto por un _input_ - que permita editar el texto y luego guardar los cambios. - - Al guardar los cambios debe cambiar de vuelta a un texto normal pero con la - información editada. - - Al recargar la página debo de poder ver los textos editados. - -### 5.7 Consideraciones técnicas Front-end - -* Separar la manipulación del DOM de la lógica (Separación de responsabilidades). -* Contar con múltiples vistas. Para esto, tu aplicación debe ser una - [Single Page Application (SPA)](https://es.wikipedia.org/wiki/Single-page_application) -* Alterar y persistir datos. Los datos que agregues o modifiques deberán - persistir a lo largo de la aplicación. Te recomendamos que uses - [Firebase](https://firebase.google.com/) para eso también. - -#### Pruebas unitarias (unit tests) - -* Recuerda que no hay un _setup_ de **tests** definido, dependerá de - la estructura de tu proyecto. Algo que no debes de olvidar es pensar en éstas - pruebas, te pueden ayudar a definir la estructura y nomenclatura de tu lógica. - -* Los tests unitarios deben cubrir un mínimo del 70% de _statements_, _functions_, - _lines_, y _branches_. - -### 5.8 Consideraciones técnicas UX - -* Hacer al menos 2 entrevistas con usuarios. -* Hacer un prototipo de baja fidelidad. -* Asegurarte de que la implementación en código siga los lineamientos del - diseño. -* Hacer sesiones de _testing de usabilidad_ con el producto en HTML. - -## 6. Hacker edition - -Las secciones llamadas _Hacker Edition_ son **opcionales**. Si **terminaste** -con todo lo anterior y te queda tiempo, intenta completarlas. Así podrás -profundizar y/o ejercitar más sobre los objetivos de aprendizaje del proyecto. - -* Permite crear posts con imágenes. -* Permite buscar usuarios, agregar y eliminar "amigos". -* Permite definir la privacidad de los _posts_ (público o solamente para amigos). -* Permite ver su muro de cualquier usuario "no-amigo" (solamente los - posts _públicos_). -* Permite comentar o responder una publicación. -* Permite editar perfil. - -## 7. Entrega - -El proyecto será _entregado_ subiendo tu código a GitHub (`commit`/`push`) y la -interfaz será desplegada usando GitHub pages u otro servicio de hosting -(Firebase, Netlify, Vercel, etc) que puedas haber encontrado en el camino. -Revisa la [documentación de Vite](https://vitejs.dev/guide/static-deploy.html) -para guiarte con eso. - -*** - -## 8. Pistas, tips y Lecturas complementarias - -Súmate al canal de Slack -[#project-social-network](https://claseslaboratoria.slack.com/archives/C03SE63GFJQ) -para conversar y pedir ayuda del proyecto. - -### Mobile first - -El concepto de [_mobile first_](https://www.mediaclick.es/blog/diseno-web-responsive-design-y-la-importancia-del-mobile-first/) -hace referencia a un proceso de diseño y desarrollo donde partimos de cómo se ve -y cómo funciona la aplicación en un dispositivo móvil primero, y más adelante se -ve como adaptar la aplicación a pantallas progresivamente grandes y -características específicas del entorno desktop. Esto es en contraposición al -modelo tradicional, donde primero se diseñaban los websites (o webapps) para -desktop y después se trataba de _arrugar_ el diseño para que entre en pantallas -más chicas. La clave acá es asegurarse de que desde el principio diseñan usando -la vista _responsive_ de las herramientas de desarrollador (developer tools) del -navegador. De esa forma, partimos de cómo se ve y comporta la aplicación en una -pantalla y entorno móvil. - -### Múltiples vistas - -En proyectos anteriores nuestras aplicaciones habían estado compuestas de una -sola _vista_ principal (una sóla _página_). En este proyecto se introduce la -necesidad de tener que dividir nuestra interfaz en varias _vistas_ o _páginas_ -y ofrecer una manera de navegar entre estas vistas. Este problema se puede -afrontar de muchas maneras: con archivos HTML independientes (cada uno con su -URL) y links tradicionales, manteniendo estado en memoria y rederizando -condicionalmente (sin refrescar la página), [manipulando el historial del -navegador](https://developer.mozilla.org/es/docs/DOM/Manipulando_el_historial_del_navegador) -con [`window.history`](https://developer.mozilla.org/es/docs/Web/API/Window/history). -En este proyecto te invitamos a explorar opciones y decidir una opción -de implementación. - -### Escritura de datos - -En los proyectos anteriores hemos consumido (leído) datos, pero todavía no -habíamos escrito datos (salvar cambios, crear datos, borrar, ...). En este -proyecto tendrás que crear (salvar) nuevos datos, así como leer, actualizar y -modificar datos existentes. Estos datos se podrán guardar de forma remota -usando [Firebase](https://firebase.google.com/). - -Para usar Firebase hay que crear un proyecto en la consola de Firebase e -instalar la dependencia `firebase` utilizando `npm`. -Lee [las instrucciones paso a paso aqui](https://firebase.google.com/docs/web/setup). - -Otras: - -* [Modulos: Export](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Sentencias/export) -* [Modulos: Import](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Sentencias/import) -* [Diseño web, responsive design y la importancia del mobile first - Media Click](https://www.mediaclick.es/blog/diseno-web-responsive-design-y-la-importancia-del-mobile-first/) -* [Mobile First: el enfoque actual del diseño web móvil - 1and1](https://www.1and1.es/digitalguide/paginas-web/diseno-web/mobile-first-la-nueva-tendencia-del-diseno-web/) -* [Mobile First - desarrolloweb.com](https://desarrolloweb.com/articulos/mobile-first-responsive.html) -* [Mobile First Is NOT Mobile Only - Nielsen Norman Group](https://www.nngroup.com/articles/mobile-first-not-mobile-only/) diff --git a/firebase-debug.log b/firebase-debug.log new file mode 100644 index 0000000..825fc18 --- /dev/null +++ b/firebase-debug.log @@ -0,0 +1,21 @@ +[debug] [2023-07-19T23:17:44.653Z] ---------------------------------------------------------------------- +[debug] [2023-07-19T23:17:44.655Z] Command: /Users/bva/.nvm/versions/node/v18.16.0/bin/node /Users/bva/.nvm/versions/node/v18.16.0/bin/firebase init +[debug] [2023-07-19T23:17:44.655Z] CLI Version: 12.4.5 +[debug] [2023-07-19T23:17:44.656Z] Platform: darwin +[debug] [2023-07-19T23:17:44.656Z] Node Version: v18.16.0 +[debug] [2023-07-19T23:17:44.663Z] Time: Wed Jul 19 2023 17:17:44 GMT-0600 (hora estándar central) +[debug] [2023-07-19T23:17:44.663Z] ---------------------------------------------------------------------- +[debug] +[debug] [2023-07-19T23:17:44.668Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"] +[debug] [2023-07-19T23:17:44.669Z] > authorizing via signed-in user (impresionesveva@gmail.com) +[info] + ######## #### ######## ######## ######## ### ###### ######## + ## ## ## ## ## ## ## ## ## ## ## + ###### ## ######## ###### ######## ######### ###### ###### + ## ## ## ## ## ## ## ## ## ## ## + ## #### ## ## ######## ######## ## ## ###### ######## + +You're about to initialize a Firebase project in this directory: + + /Users/bva/Desktop/DEV008-social-network + diff --git a/package.json b/package.json index 1d89e14..60e8091 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "pretest": "npm run htmlhint && npm run eslint && npm run stylelint", "test": "jest --coverage", "dev": "vite dev src", - "start": "npm run dev", + "start": "npm run dev ", "build": "vite build", "preview": "vite preview" }, @@ -41,5 +41,12 @@ "createdAt": "2023-06-06T21:37:46.504Z", "version": "6.3.0", "commit": "a942adeb868f1fe54b86e34cc4fc4ddb0601700d" - } -} \ No newline at end of file + }, + "dependencies": { + "firebase": "^10.0.0" + }, + "directories": { + "test": "test" + }, + "author": "" +} diff --git a/readme imagenes/HU.jpg b/readme imagenes/HU.jpg new file mode 100644 index 0000000..b890e2d Binary files /dev/null and b/readme imagenes/HU.jpg differ diff --git a/readme imagenes/HomeImg.jpeg b/readme imagenes/HomeImg.jpeg new file mode 100644 index 0000000..c509f4a Binary files /dev/null and b/readme imagenes/HomeImg.jpeg differ diff --git a/readme imagenes/Login.jpeg b/readme imagenes/Login.jpeg new file mode 100644 index 0000000..290e556 Binary files /dev/null and b/readme imagenes/Login.jpeg differ diff --git a/readme imagenes/feed.jpeg b/readme imagenes/feed.jpeg new file mode 100644 index 0000000..105b790 Binary files /dev/null and b/readme imagenes/feed.jpeg differ diff --git a/readme imagenes/formulario.jpeg b/readme imagenes/formulario.jpeg new file mode 100644 index 0000000..97a266b Binary files /dev/null and b/readme imagenes/formulario.jpeg differ diff --git a/readme imagenes/prototipo baja.png b/readme imagenes/prototipo baja.png new file mode 100644 index 0000000..e194850 Binary files /dev/null and b/readme imagenes/prototipo baja.png differ diff --git a/readme imagenes/prototipo2alta.jpg b/readme imagenes/prototipo2alta.jpg new file mode 100644 index 0000000..8d6564f Binary files /dev/null and b/readme imagenes/prototipo2alta.jpg differ diff --git a/readme imagenes/prototipoalta.jpg b/readme imagenes/prototipoalta.jpg new file mode 100644 index 0000000..48745b6 Binary files /dev/null and b/readme imagenes/prototipoalta.jpg differ diff --git a/readme imagenes/prototipobaja.jpg b/readme imagenes/prototipobaja.jpg new file mode 100644 index 0000000..7643223 Binary files /dev/null and b/readme imagenes/prototipobaja.jpg differ diff --git a/readme imagenes/register.jpeg b/readme imagenes/register.jpeg new file mode 100644 index 0000000..8ffedf1 Binary files /dev/null and b/readme imagenes/register.jpeg differ diff --git a/readme imagenes/trello.jpeg b/readme imagenes/trello.jpeg new file mode 100644 index 0000000..59a173e Binary files /dev/null and b/readme imagenes/trello.jpeg differ diff --git a/src/Another America.ttf b/src/Another America.ttf new file mode 100644 index 0000000..6414a1b Binary files /dev/null and b/src/Another America.ttf differ diff --git a/src/CaviarDreams.ttf b/src/CaviarDreams.ttf new file mode 100644 index 0000000..852f454 Binary files /dev/null and b/src/CaviarDreams.ttf differ diff --git a/src/EDITAR.png b/src/EDITAR.png new file mode 100755 index 0000000..39e4ac7 Binary files /dev/null and b/src/EDITAR.png differ diff --git a/src/borrar.png b/src/borrar.png new file mode 100755 index 0000000..9878595 Binary files /dev/null and b/src/borrar.png differ diff --git a/src/components/feed.js b/src/components/feed.js new file mode 100644 index 0000000..3868de1 --- /dev/null +++ b/src/components/feed.js @@ -0,0 +1,283 @@ +import { crearPost, mostrarpost, borrarPost, incrementarLike , obtenerDocumento, decrementarLike, editPost} from '../firestore/baseDeDatosFirestore.js'; +//import { usuarioActual } from '../lib/firebase/configuracionFirabase.js'; +import { obtenerUsuarioActual } from '../lib/localStorage.js'; + +export const feed = (onNavigate) => { + const usuarioActual = obtenerUsuarioActual(); + console.log(usuarioActual); + + const homeDiv = document.createElement('div'); + homeDiv.classList.add('homeDiv'); + + const headerFeed = document.createElement('header'); + headerFeed.classList.add('headerFeed'); + homeDiv.appendChild(headerFeed); + + const containerLogo = document.createElement('div'); + containerLogo.classList.add('containerLogo'); + headerFeed.appendChild(containerLogo); + + const headerLogo = document.createElement('img'); + headerLogo.src = '../logo.png'; + headerLogo.classList.add('headerLogoFeed'); + containerLogo.appendChild(headerLogo); + + const usuarioInfoHeader = document.createElement('div'); + usuarioInfoHeader.classList.add('usuarioInfoHeader'); + headerFeed.appendChild(usuarioInfoHeader); + + const imagenUsuarioHeader = document.createElement('img'); + imagenUsuarioHeader.className = 'imagenUsuarioHeader'; + usuarioInfoHeader.appendChild(imagenUsuarioHeader); + imagenUsuarioHeader.src = 'gatogif.gif'; + + const nombreUsuarioHeader = document.createElement('h2'); + nombreUsuarioHeader.className = 'nombreUsuarioHeader'; + nombreUsuarioHeader.innerText = usuarioActual.email; + usuarioInfoHeader.appendChild(nombreUsuarioHeader); + + const buttonCerrarSesion = document.createElement('button'); + buttonCerrarSesion.classList.add('buttonCerrarSesion'); + buttonCerrarSesion.textContent = 'Salir'; + usuarioInfoHeader.appendChild(buttonCerrarSesion); + + const feedDiv = document.createElement('div'); + feedDiv.classList.add('feedContainer'); + homeDiv.appendChild(feedDiv); + + const crearPostContainer = document.createElement('div'); + crearPostContainer.classList.add('crearPostContainer'); + feedDiv.appendChild(crearPostContainer); + + const textContainer = document.createElement('div'); + textContainer.classList.add('textContainer'); + crearPostContainer.appendChild(textContainer); + + const usuarioInfo = document.createElement('section'); + usuarioInfo.className = 'usuarioInfo'; + textContainer.appendChild(usuarioInfo); + + const imagenUsuario = document.createElement('img'); + imagenUsuario.className = 'imagenUsuario'; + imagenUsuario.src = 'giphy (1).gif'; + usuarioInfo.appendChild(imagenUsuario); + + const nombreUsuario = document.createElement('p'); + nombreUsuario.className = 'nombreUsuario'; + nombreUsuario.innerText = usuarioActual.email; + usuarioInfo.appendChild(nombreUsuario); + + const publicar = document.createElement('textarea'); + publicar.classList.add('publicarInput'); + publicar.id = 'crearPost'; + publicar.placeholder = 'Crear post'; + textContainer.appendChild(publicar); + + const buttonPublicar = document.createElement('button'); + buttonPublicar.className = 'buttonPublicar'; + buttonPublicar.id = 'botonPublicar'; + buttonPublicar.textContent = 'Publicar'; + textContainer.appendChild(buttonPublicar); + //se da una evento onclick al buttonPublicar para que mande a llamar la funcion postPublicado--------------- + buttonPublicar.onclick = function () { + postPublicado(post); + //imprime en consola los post publicados---------------- + console.log(postPublicado) + }; + + // funcion que crea el contenedor de cada post---------------------------- + function contenedorPost(post) { + + const postFeedContainer = document.createElement('div'); + postFeedContainer.classList.add('postFeedContainer'); + feedDiv.appendChild(postFeedContainer); + + const textContainerpost = document.createElement('div'); + textContainerpost.classList.add('textContainerpost'); + postFeedContainer.appendChild(textContainerpost); + textContainerpost.id = 'textContainerpost'; + + const usuarioInfoPost = document.createElement('section'); + usuarioInfoPost.className = 'usuarioInfo'; + textContainerpost.appendChild(usuarioInfoPost); + + const imagenUsuariopost = document.createElement('img'); + imagenUsuariopost.className = 'imagenUsuario'; + imagenUsuariopost.src = 'giphy.gif'; + usuarioInfoPost.appendChild(imagenUsuariopost); + + const nombreUsuariopost = document.createElement('p'); + nombreUsuariopost.className = 'nombreUsuario'; + nombreUsuariopost.innerText = post.data().autor; + nombreUsuariopost.id = 'nombreDeUsuario'; + usuarioInfoPost.appendChild(nombreUsuariopost); + + const publicacion = document.createElement('textarea'); + publicacion.classList.add('publicarInput'); + publicacion.innerText = post.data().contenido; + publicacion.disabled = true; + publicacion.id = 'post'; + publicacion.placeholder = 'Post'; + textContainerpost.appendChild(publicacion); + + const opcionesPostContenedor = document.createElement('div'); + opcionesPostContenedor.className = 'opcionesPostContenedor'; + textContainerpost.appendChild(opcionesPostContenedor); + + const containerLike = document.createElement('button'); + containerLike.classList.add('containerLike'); + containerLike.id = ' containerLike'; + opcionesPostContenedor.appendChild(containerLike); + + + containerLike.addEventListener("click", function () { + obtenerDocumento(post.id) + .then( (documento)=> { + const yaDioLike = documento.data().likes.includes(usuarioActual.uid) + if (yaDioLike){ + decrementarLike(usuarioActual.uid, post.id).then(()=>{ + window.location.reload() + }) + } + else{ + play(), + incrementarLike(post.id, usuarioActual.uid).then(()=>{ + window.location.reload(); + }) + } + }) + .catch((error)=>{ + console.log(error) + }) + /* incrementarLike(post.id, usuarioActual.uid).then((respuesta) => { + console.log(respuesta); + console.log('Diste un like'); + console.log(post.uid); + alert("funciona el boton") + }) + .catch((error) => { + const errorCode = error.code; + const errorMessage = error.message; + console.log(errorCode); + console.log(errorMessage); + alert(error.message); + window.location.reload(); // Para recargar la pantalla// + });*/ + }); + + + const likeFuego = document.createElement('img'); + likeFuego.src = 'https://images.emojiterra.com/google/noto-emoji/unicode-15/animated/1f525.gif'; + likeFuego.classList.add('likeFuego'); + containerLike.appendChild(likeFuego); + + const contadorLikes = document.createElement('number'); + contadorLikes.className = 'contadorLikes'; + contadorLikes.id = 'contadorLikes'; + contadorLikes.textContent = post.data().likes.length; + console.log(post); + containerLike.appendChild(contadorLikes); + + if (usuarioActual.email === post.data().autor){ + const containerPostMenu = document.createElement('div'); + containerPostMenu.classList = ('containerPostMenu'); + opcionesPostContenedor.appendChild(containerPostMenu); + + const editarPost = document.createElement('img'); + editarPost.src = 'EDITAR.png'; + editarPost.classList.add('editarPost'); + containerPostMenu.appendChild(editarPost); + editarPost.addEventListener("click", () => { + alert('Edita tu post'); + publicacion.disabled = false; + + }); + + const guardarPost = document.createElement('img'); + guardarPost.src = 'guardar.png'; + guardarPost.classList.add('guardarPost'); + containerPostMenu.appendChild(guardarPost); + guardarPost.addEventListener("click", () => { + alert('Editaste tu post'); + const nuevoContenido = publicacion.value; + console.log(nuevoContenido); + editPost(post.id, nuevoContenido) + .then((respuesta) => { + publicacion.disabled= true; + console.log(respuesta); + }) + .catch((error)=>{ + console.log(error)}) + }); + + const eliminarPost = document.createElement('img'); + eliminarPost.src = 'borrar.png'; + eliminarPost.classList.add('eliminarPost'); + containerPostMenu.appendChild(eliminarPost); + eliminarPost.addEventListener('click', () => { + const alertConfimar = confirm('¿Eliminar post?'); // Confirmación para eliminar post// NO FUNCIONA / LO BORRA DE TODOS MODOS// + if (alertConfimar === true) { + borrarPost(post.id) + .then((respuesta) => { + console.log(respuesta); + console.log('Borraste un post'); + window.location.reload(); + }) + .catch((error) => { + const errorCode = error.code; + const errorMessage = error.message; + console.log(errorCode); + console.log(errorMessage); + alert(error.message); + window.location.reload(); + }); + } + }); + //console.log(post.id); + }; + }; + + //funcion mostrarPost hace un recorrido de cada post y en cada uno se manda a llamar la funcion contenedorPost---------- + mostrarpost().then((respuesta) => { + respuesta.forEach((post) => { + contenedorPost(post); + //console.log(post.data().contenido); + //para acceder a la info de post es con post.data.contenido o fecha o autor---------------- + }); + }); + + buttonCerrarSesion.addEventListener('click', () => onNavigate('/')); + + + buttonPublicar.addEventListener('click', (e) => { + e.preventDefault(); + + const userPost = usuarioActual.email; + console.log(userPost); + const contenidoPost = document.getElementById('crearPost').value; + console.log(contenidoPost); + const fecha = new Date(); + const fechaPost = fecha.toLocaleDateString(); + console.log(fechaPost); + + crearPost(userPost, contenidoPost, fechaPost) + .then((respuesta) => { + // Signed in + const postCreado = respuesta; + console.log(postCreado); + // ... + console.log('Haz creado un post'); + window.location.reload(); // Para recargar la pantalla// + }) + .catch((error) => { + const errorCode = error.code; + const errorMessage = error.message; + console.log(errorCode); + console.log(errorMessage); + alert(error.message); + window.location.reload(); // Para recargar la pantalla// + }); + }); + + return homeDiv; +}; \ No newline at end of file diff --git a/src/components/home.js b/src/components/home.js new file mode 100644 index 0000000..d8ee067 --- /dev/null +++ b/src/components/home.js @@ -0,0 +1,51 @@ +export const home = (onNavigate) => { + const homeDiv = document.createElement('div'); + + const contenedorHome = document.createElement('div'); + contenedorHome.className = 'contenedorHome'; + homeDiv.appendChild(contenedorHome); + + const logoPrincipal = document.createElement('img'); + logoPrincipal.className = 'logoPrincipal'; + contenedorHome.appendChild(logoPrincipal); + logoPrincipal.src = 'logo.png'; + + const sinopsis = document.createElement('p'); + sinopsis.className = 'sinopsis'; + sinopsis.textContent = 'Se trata de una app en la que es posible compartir canciones y álbumes con los contactos, que podrán escuchar usando cualquier servicio de streaming que tengan contratado, desde Spotify a Apple Music, pasando por Deezer y otros.Jamselect permite descubrir nuevos ritmos y hablar sobre ellos, crear un hilo de comentarios sobre cada canción compartida, siendo este su principal punto de ventaja con respecto a otras soluciones semejantes (como compartir una lista a través de un enlace, por ejemplo).'; + contenedorHome.appendChild(sinopsis); + + const contenedorBotones = document.createElement('div'); + contenedorBotones.className = 'contenedorBotonesHome'; + contenedorHome.appendChild(contenedorBotones); + + const buttonRegister = document.createElement('button'); + buttonRegister.innerText = 'Registrarse'; + buttonRegister.classList = 'button'; + contenedorBotones.appendChild(buttonRegister); + + const buttonLogin = document.createElement('button'); + buttonLogin.innerText = 'Entrar'; + buttonLogin.classList = 'button'; + contenedorBotones.appendChild(buttonLogin); + + const contenedorImagenesH = document.createElement('div'); + contenedorImagenesH.className = 'contenedorImagenesH'; + contenedorHome.appendChild(contenedorImagenesH); + + const imagenAbajoH = document.createElement('img'); + imagenAbajoH.className = 'imagenAbajo'; + contenedorImagenesH.appendChild(imagenAbajoH); + imagenAbajoH.src = 'imageninicio.png'; + + const footer = document.createElement('footer'); + footer.className = 'footer'; + homeDiv.appendChild(footer); + + buttonRegister.addEventListener('click', () => onNavigate('/register')); + buttonLogin.addEventListener('click', () => onNavigate('/login')); + + homeDiv.appendChild(contenedorHome); + + return homeDiv; +}; diff --git a/src/components/login.js b/src/components/login.js new file mode 100644 index 0000000..819624f --- /dev/null +++ b/src/components/login.js @@ -0,0 +1,121 @@ +import { iniciarSesion, accesoGoogle } from '../lib/firebase/configuracionFirabase'; +import { guardarUsuarioActual } from '../lib/localStorage'; + +export const login = (onNavigate) => { + const homeDiv = document.createElement('div'); + homeDiv.classList.add('container'); + + const contenedorImagen = document.createElement('aside'); + contenedorImagen.classList.add('contenedorImagen'); + homeDiv.appendChild(contenedorImagen); + + const loginImg = document.createElement('img'); + loginImg.src = '../img_login.png'; + loginImg.classList.add('loginImagen'); + contenedorImagen.appendChild(loginImg); + + const contenedorFormulario = document.createElement('form'); + contenedorFormulario.classList.add('contenedorFormulario'); + homeDiv.appendChild(contenedorFormulario); + + const headerLogo = document.createElement('img'); + headerLogo.src = '../logo.png'; + headerLogo.classList.add('headerLogo'); + contenedorFormulario.appendChild(headerLogo); + + const inputCorreo = document.createElement('input'); + inputCorreo.placeholder = 'Correo'; + inputCorreo.classList.add('input'); + inputCorreo.id = 'correo'; + inputCorreo.required = true; + contenedorFormulario.appendChild(inputCorreo); + + const inputContraseña = document.createElement('input'); + inputContraseña.placeholder = 'Constraseña'; + inputContraseña.classList.add('input'); + inputContraseña.id = 'contraseña'; + inputContraseña.required = true; + contenedorFormulario.appendChild(inputContraseña); + inputContraseña.type = ('password'); + + const buttonEntrar = document.createElement('button'); + buttonEntrar.classList.add('button'); + buttonEntrar.textContent = 'Entrar'; + contenedorFormulario.appendChild(buttonEntrar); + + const textoAccederCon = document.createElement('p'); + textoAccederCon.textContent = 'Acceder con:'; + contenedorFormulario.appendChild(textoAccederCon); + + const buttonGoogle = document.createElement('img'); + buttonGoogle.src = 'https://cdn.pixabay.com/photo/2021/05/24/09/15/google-logo-6278331_1280.png'; + buttonGoogle.classList.add('buttonGoogle'); + contenedorFormulario.appendChild(buttonGoogle); + + const textoRegistrateAqui = document.createElement('p'); + textoRegistrateAqui.textContent = 'Si no tienes cuenta registrate aquí'; + contenedorFormulario.appendChild(textoRegistrateAqui); + + const buttonRegister = document.createElement('button'); + buttonRegister.classList.add('button'); + buttonRegister.textContent = 'Registrate'; + contenedorFormulario.appendChild(buttonRegister); + + const buttonHome = document.createElement('button'); + buttonHome.classList.add('button'); + buttonHome.textContent = 'Inicio'; + contenedorFormulario.appendChild(buttonHome); + + buttonRegister.addEventListener('click', () => onNavigate('/register')); + + buttonHome.addEventListener('click', () => onNavigate('/')); + + buttonEntrar.addEventListener('click', (e) => { + e.preventDefault(); + const email = document.getElementById('correo').value; + const password = document.getElementById('contraseña').value; + + iniciarSesion(email, password) + .then((respuesta) => { + // Signed in + const user = respuesta.user; + console.log(user); + guardarUsuarioActual(user); + // ... + alert('Bienvenido'); + onNavigate('/feed'); + }) + .catch((error) => { + const errorCode = error.code; + const errorMessage = error.message; + console.log(errorCode); + console.log(errorMessage); + alert(error.message); + }); + }); + buttonGoogle.addEventListener('click', (e) => { + e.preventDefault(); + accesoGoogle().then((result) => { + const user = result.user; + console.log(user.email); + guardarUsuarioActual(user); + // IdP data available using getAdditionalUserInfo(result) + // ... + alert('Bienvenido'); + onNavigate('/feed'); + }).catch((error) => { + // Handle Errors here. + const errorCode = error.code; + const errorMessage = error.message; + console.log(errorCode); + console.log(errorMessage); + // The email of the user's account used. + const email = error.customData.email; + console.log(email); + // ... + alert(error.message); + }); + }); + + return homeDiv; +}; diff --git a/src/components/register.js b/src/components/register.js new file mode 100644 index 0000000..035148d --- /dev/null +++ b/src/components/register.js @@ -0,0 +1,129 @@ +import { crearUsuario, accesoGoogle } from '../lib/firebase/configuracionFirabase'; +// import { getAuth, createUserWithEmailAndPassword } from "firebase/auth"; +// import { auth } from "../lib/firebase/configuracionFirabase"; + +export const register = (onNavigate) => { + const homeDiv = document.createElement('div'); + homeDiv.classList.add('container'); + + const registerDiv = document.createElement('main'); + registerDiv.classList.add('registerDiv'); + homeDiv.appendChild(registerDiv); + + const conteImagen = document.createElement('aside'); + conteImagen.classList.add('contenedorImagen'); + registerDiv.appendChild(conteImagen); + + const registerImg = document.createElement('img'); + registerImg.src = '../registro.png'; + registerImg.classList.add('loginImagen'); + conteImagen.appendChild(registerImg); + + const contenedorInput = document.createElement('form'); + contenedorInput.classList.add('contenedorFormulario'); + registerDiv.appendChild(contenedorInput); + + const headerLogo = document.createElement('img'); + headerLogo.src = '../logo.png'; + headerLogo.classList.add('headerLogo'); + contenedorInput.appendChild(headerLogo); + + const userInput = document.createElement('input'); + userInput.classList.add('input'); + userInput.id = 'nombre'; + userInput.placeholder = 'Nombre de usuario'; + userInput.required = false; + + const emailInput = document.createElement('input'); + emailInput.classList.add('input'); + emailInput.id = 'mail'; + emailInput.placeholder = 'Correo electrónico'; + emailInput.required = true; + + const passwordInput = document.createElement('input'); + passwordInput.classList.add('input'); + passwordInput.id = 'contraseña1'; + passwordInput.placeholder = 'Crear contraseña (al menos 8 caracteres)'; + passwordInput.required = true; + passwordInput.minLength = 8; + passwordInput.type = ('password'); + + const aceptregister = document.createElement('button'); + aceptregister.classList.add('button'); + aceptregister.textContent = 'Registrar'; + + const buttonHome = document.createElement('button'); + buttonHome.classList.add('button'); + buttonHome.textContent = 'Inicio'; + + const links = document.createElement('section'); + + const parrafo1 = document.createElement('p'); + parrafo1.textContent = 'Ó registrate con tu cuenta'; + + const linkGoogle = document.createElement('div'); + links.appendChild(linkGoogle); + + const buttonGoogle = document.createElement('img'); + buttonGoogle.src = 'https://cdn.pixabay.com/photo/2021/05/24/09/15/google-logo-6278331_1280.png'; + buttonGoogle.classList.add('buttonGoogle'); + buttonGoogle.id = 'google'; + + buttonHome.addEventListener('click', () => onNavigate('/')); + contenedorInput.appendChild(userInput); + contenedorInput.appendChild(emailInput); + contenedorInput.appendChild(passwordInput); + contenedorInput.appendChild(aceptregister); + links.appendChild(parrafo1); + contenedorInput.appendChild(links); + contenedorInput.appendChild(buttonGoogle); + contenedorInput.appendChild(buttonHome); + + aceptregister.addEventListener('click', (e) => { + e.preventDefault(); + const email = document.getElementById('mail').value; + const password = document.getElementById('contraseña1').value; + + crearUsuario(email, password) + .then((respuesta) => { + // Signed in + const user = respuesta.user; + console.log(user); + // ... + alert('Usuario registrado exitosamente'); + onNavigate('/login'); + }) + .catch((error) => { + const errorCode = error.code; + const errorMessage = error.message; + console.log(errorCode); + console.log(errorMessage); + // .. + alert(error.message); + }); + }); + + buttonGoogle.addEventListener('click', (e) => { + e.preventDefault(); + accesoGoogle().then((result) => { + const user = result.user; + console.log(user); + // IdP data available using getAdditionalUserInfo(result) + // ... + alert('Bienvenido(a)'); + onNavigate('/feed'); + }).catch((error) => { + // Handle Errors here. + const errorCode = error.code; + const errorMessage = error.message; + console.log(errorCode); + console.log(errorMessage); + // The email of the user's account used. + const email = error.customData.email; + console.log(email); + // ... + alert(error.message); + }); + }); + return homeDiv; +}; diff --git a/src/firestore/baseDeDatosFirestore.js b/src/firestore/baseDeDatosFirestore.js new file mode 100644 index 0000000..ebc9844 --- /dev/null +++ b/src/firestore/baseDeDatosFirestore.js @@ -0,0 +1,53 @@ +import { getFirestore, collection, addDoc, getDocs, deleteDoc, doc, setDoc, getDoc , updateDoc, arrayUnion, arrayRemove} from 'firebase/firestore'; +import { app } from '../lib/firebase/configuracionFirabase'; + +const db = getFirestore(app); + +export function crearPost(userAutor, userContenido, fechaHoy) { + const referenciaColeccion = collection(db, 'Posts'); + console.log(referenciaColeccion); + const datosPost = { + autor: userAutor, + contenido: userContenido, + fecha: fechaHoy, + likes: [], + }; + console.log(datosPost); + return addDoc(referenciaColeccion, datosPost); +} + +export function mostrarpost() { + const referenciaColeccion = collection(db, 'Posts'); + return getDocs(referenciaColeccion); +} + +export function borrarPost(id) { + const referenciaDocumento = doc(db, 'Posts', id); + return deleteDoc(referenciaDocumento); +} + +export function incrementarLike(postId,userId){ +const referenciaDocumento = doc(db, 'Posts', postId); +return updateDoc(referenciaDocumento, {likes: arrayUnion(userId)}) +} + + +export function decrementarLike(userId,postId){ + const referenciaDocumento = doc(db, 'Posts', postId); + return updateDoc(referenciaDocumento, {likes: arrayRemove(userId)}) +} + + +export function obtenerDocumento (id){ + const referenciaDocumento = doc(db, 'Posts', id); + return getDoc(referenciaDocumento) +}; + + +//hacer el listener para el agregar y quitar like +//luego el usuario en localstorage + +export function editPost (id, contenidoEditado) { + const referenciaDocumento = doc(db, 'Posts', id); + return updateDoc (referenciaDocumento, {contenido: (contenidoEditado)}) +} \ No newline at end of file diff --git a/src/fondofeed5.jpg b/src/fondofeed5.jpg new file mode 100755 index 0000000..14a70bf Binary files /dev/null and b/src/fondofeed5.jpg differ diff --git a/src/gatogif.gif b/src/gatogif.gif new file mode 100644 index 0000000..64d8548 Binary files /dev/null and b/src/gatogif.gif differ diff --git a/src/giphy (1).gif b/src/giphy (1).gif new file mode 100644 index 0000000..346c564 Binary files /dev/null and b/src/giphy (1).gif differ diff --git a/src/giphy.gif b/src/giphy.gif new file mode 100644 index 0000000..bcabb3d Binary files /dev/null and b/src/giphy.gif differ diff --git a/src/guardar.png b/src/guardar.png new file mode 100755 index 0000000..fec41ff Binary files /dev/null and b/src/guardar.png differ diff --git a/src/imageninicio.png b/src/imageninicio.png new file mode 100755 index 0000000..1c9ec3c Binary files /dev/null and b/src/imageninicio.png differ diff --git a/src/img_login.png b/src/img_login.png new file mode 100644 index 0000000..80f153d Binary files /dev/null and b/src/img_login.png differ diff --git a/src/index.html b/src/index.html index 788db3c..dcaa509 100644 --- a/src/index.html +++ b/src/index.html @@ -4,9 +4,24 @@ - Document + + + + +
+ + + + + \ No newline at end of file diff --git a/src/lib/firebase/configuracionFirabase.js b/src/lib/firebase/configuracionFirabase.js new file mode 100644 index 0000000..499ae1d --- /dev/null +++ b/src/lib/firebase/configuracionFirabase.js @@ -0,0 +1,47 @@ +import { initializeApp } from 'firebase/app'; +import { getAuth, createUserWithEmailAndPassword, signInWithEmailAndPassword, signInWithPopup, GoogleAuthProvider, onAuthStateChanged } from 'firebase/auth'; + +// TODO: Add SDKs for Firebase products that you want to use +// https://firebase.google.com/docs/web/setup#available-libraries + +// Your web app's Firebase configuration +// For Firebase JS SDK v7.20.0 and later, measurementId is optional +const firebaseConfig = { + apiKey: 'AIzaSyBQXn4nU0mnSLYOnYiB6qXhtGDlsgK8IMk', + authDomain: 'musiclub-sn.firebaseapp.com', + projectId: 'musiclub-sn', + storageBucket: 'musiclub-sn.appspot.com', + messagingSenderId: '752819709886', + appId: '1:752819709886:web:2c51aad56c608e393b7bef', + measurementId: 'G-4WTX2542QZ', +}; +// Initialize Firebase +export const app = initializeApp(firebaseConfig); + +const auth = getAuth(app); + +export const usuarioActual = onAuthStateChanged(auth, (user) => { + const displayName = user.displayName; + // console.log(displayName); + // console.log(user.email); + // console.log(user); + return displayName; +}); + +/*const user = auth.currentUser; +console.log(user);*/ + +console.log(app.name); + +export const crearUsuario = (email, password) => { + return createUserWithEmailAndPassword(auth, email, password) +}; + +export const iniciarSesion = (email, password) => { + return signInWithEmailAndPassword(auth, email, password) +}; + +export const accesoGoogle = () => { + const provider = new GoogleAuthProvider(); + return signInWithPopup(auth, provider); +}; diff --git a/src/lib/localStorage.js b/src/lib/localStorage.js new file mode 100644 index 0000000..4ab67a1 --- /dev/null +++ b/src/lib/localStorage.js @@ -0,0 +1,12 @@ +export function guardarUsuarioActual(user) { + return localStorage.setItem('usuarioActual', JSON.stringify(user)); +} + +export function obtenerUsuarioActual() { + const usuarioActual = JSON.parse(localStorage.getItem('usuarioActual')); + return usuarioActual; +} + +export function eliminarUsuarioActual() { + localStorage.removeItem('usuarioActual'); +} diff --git a/src/logo.png b/src/logo.png new file mode 100755 index 0000000..da8502f Binary files /dev/null and b/src/logo.png differ diff --git a/src/logoChico.png b/src/logoChico.png new file mode 100755 index 0000000..da8502f Binary files /dev/null and b/src/logoChico.png differ diff --git a/src/main.js b/src/main.js index ac27e91..72ffd4c 100644 --- a/src/main.js +++ b/src/main.js @@ -1,5 +1,35 @@ -// Este es el punto de entrada de tu aplicacion +import { home } from './components/home.js'; +import { register } from './components/register.js'; +import { login } from './components/login.js'; +import { feed } from './components/feed.js'; -import { myFunction } from './lib/index.js'; +const rootDiv = document.getElementById('root'); -myFunction(); +const routes = { + '/': home, + '/register': register, + '/login': login, + '/feed': feed, +}; + +export const onNavigate = (pathname) => { + window.history.pushState( + {}, + pathname, + window.location.origin + pathname, + ); + + while (rootDiv.firstChild) { + rootDiv.removeChild(rootDiv.firstChild); + } + + rootDiv.appendChild(routes[pathname](onNavigate)); +}; + +const component = routes[window.location.pathname]; + +window.onpopstate = () => { + rootDiv.appendChild(component(onNavigate)); +}; + +rootDiv.appendChild(component(onNavigate)); \ No newline at end of file diff --git a/src/registro.png b/src/registro.png new file mode 100755 index 0000000..ce83b25 Binary files /dev/null and b/src/registro.png differ diff --git a/src/sonido2.mp3 b/src/sonido2.mp3 new file mode 100644 index 0000000..15e963a Binary files /dev/null and b/src/sonido2.mp3 differ diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..9d3cd63 --- /dev/null +++ b/src/style.css @@ -0,0 +1,446 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + } +@font-face { + font-family: AnotherAmerica; + src: url(Another\ America.ttf); +} +@font-face { + font-family: CaviarDreams; + src: url(CaviarDreams.ttf); +} +@media (max-width:600px) { + .container { + display: flex; + flex-wrap:wrap ; + justify-content: center; + width: 100%; + height: 100%; + } +} + .container { + display: flex; + background-color: #eceaea; + width: 100%; + height: 100%; + } + .contenedorImagen { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100vh; + background-color: black; + } + .loginImagen { + width: 600px; + height: 600px; + } + .contenedorFormulario { + display: flex; + flex-direction: column; + justify-content: space-evenly; + align-items: center; + width: 100vh; + height: 100vh; + padding: 3rem; + font-size: 1.5rem; + font-family: CaviarDreams; + background: #eceaea + } + .headerLogo { + width: 30rem; + height: 8rem; + margin: 1rem 1rem 2rem 1rem; + } + .input { + border-radius: 2rem; + text-align: center; + font-size: 1.2rem; + font-family: CaviarDreams; + padding: 5px; + width: 3.4rem; + height: 3.2rem; + margin: 1%; + color: black; + } + .input::placeholder{ + color: rgb(219, 113, 13); + font-weight: bold ; + } + .input:hover { + transform: scale(1.1); + } + .button { + border-radius: 1rem; + padding: .3rem .8rem; + color: white; + background-color:#bb2525; + cursor: pointer; + font-size: 1.3rem; + font-family: AnotherAmerica; + letter-spacing:.5rem; + margin: 1rem; + margin-left: 20px; + } + .button:hover { + transform: scale(1.1); + } + .buttonGoogle { + width: 3rem; + height: 3rem; + margin: .5rem; + cursor: pointer; + } + .buttonGoogle:hover { + transform: scale(1.1); + } + +/*---------------------------Estilo home-------------------*/ + + body { + background: #eceaea; + background-repeat: no-repeat; + overflow-x: hidden; + width: 100%; + height:auto; + } + .contenedorHome{ + height: 100%; + width: 100%; + justify-content: center; + text-align: center; + } + .logoPrincipal{ + height: 120px; + margin: 30px; + justify-content: center; + text-align: center; + align-items: center; + width: 50%; + height: auto; + } + .sinopsis{ + color: white; + font-size: larger; + background-color: black; + padding: 30px; + justify-content: center; + align-items: center; + font-family: CaviarDreams; +} +.contenedorBotonesHome{ + justify-content: center; + align-items: center; + padding: 20px; + display: flex; + margin: 20px; +} +.imagenAbajo{ + width: 100%; + position: bottom; + justify-content: center; + align-items: center; +} + + /*======================= REGISTER ======================== */ + + + .registerDiv { + display: flex; + background-color: #eceaea; + width: 100%; + height: 100%; + } + + +/* ===== Media Querys Pantallas desde 769 px de ancho ===== */ + +@media (max-width:900px) +{ + .loginImagen,.contenedorImagen{ + width: 0; + height: 0; + } + .buttonGoogle{ + width: auto; + display: flex; + flex-wrap:wrap ; + justify-content: center; + width: 10%; + height: 10%; + } + .registerDiv, .contenedorFormulario, .input, .button, .headerLogo { + width: auto; + display: flex; + flex-wrap:wrap ; + justify-content: center; + width: 100%; + height: 100%; + } +} + @media (min-width:280px){ + .registerDiv, .contenedorFormulario, .input, .button, .headerLogo { + width: 100%; + display: flex; + justify-content:center; + height: 100%; + } +}; + +/* Feed */ + +.homeDiv{ + display: flex; + width: 100%; + height: 100%; + background-color: black; +} +.feedDiv { + display: flex; + width: 100%; + height: 100%; + background-color: black; +} +.headerFeed { + justify-content: center; + display:inline-block; + align-items: center; + justify-content: space-between; + align-items: center; + width: 100%; + height: auto; + background-color:#eceaea; +} +.containerLogo{ + justify-content: center; + display: flex; + width: 100%; + margin-top: 10px; +} +.headerLogoFeed{ + display: flex; + width: 200px; + height: auto; +} +.usuarioInfoHeader{ + background-color:#282828; + display: flex; + width: 100%; + height: auto; + align-items:center; + justify-content: center; +} +.imagenUsuarioHeader{ + display: flex; + width: auto; + height: 50px; + margin: 10px; + margin-top: 15px; + border-radius: 100%; + border-width: 3px; + border-style:outset; + border-color: black; +} +.nombreUsuarioHeader{ + color: white; + display: flex; + width: auto; + height: auto; + display: flex; + font-family: CaviarDreams; + font-size: 20px; + margin: 10px; +} +.feedContainer { + display: flex; + flex-direction: column; + justify-content: space-around; + align-items: center; + background-image: url(fondofeed5.jpg); + background-size: auto; + padding: 2% 20%; + +} +/*crear solo un estilo para los containers de post que se acoplen al texto*/ + +.buttonCerrarSesion{ + border-radius: 1rem; + padding: .2rem .8rem; + color: white; + background-color:#bb2525; + cursor: pointer; + font-size: 1.2rem; + font-family: AnotherAmerica; + letter-spacing:.3rem; + margin: 10px; + margin-top: 15px; +} +.crearPostContainer{ + position: relative; + display: flex; + justify-content: center; + align-items: center; + padding: 10px; + background-color: #2828289d; + width: 115%; + height: 40%; + border-radius: 1rem; + +} +.postFeedContainer{ + position:relative; + display: flex; + align-items: center; + background-color: #2828289d; + width: 115%; + height: auto; + border-radius: 1rem; + padding: 5px; + margin-top: 20px; + justify-content: space-around; +} +.textContainer{ + display: flex; + flex-direction: column; + background-color: #EB6C36; + width: 875px; + height: 200px; + border-radius: 2rem; + padding: 15px 15px 6px 15px; + margin: 20px; + border-width: 4px; + border-style:outset; + border-color: black; + +} +.usuarioInfo{ + display: flex; + align-items: center; + margin-bottom: 1%; +} +.imagenUsuario { + width: 40px; + height: 40px; + margin-right: 1%; + border-radius: 100%; + border-width: 2px; + border-style:outset; + border-color: black; +} +.nombreUsuario{ + font-size: large; + font-family: CaviarDreams; + font-weight:bold; + color: #eceaea; + font-weight:bold; + margin-left: 5px; +} +.publicarInput{ + display: flex; + justify-content: center; + align-items: center; + background-color: white; + width: 100%; + height: 55%; + border-radius: 1rem; + border-color: white; + padding: 10px; + border-width: 3px; + border-style:ridge; + border-color: black; +} +.buttonPublicar{ + align-self: flex-end; + border-radius: 1rem; + padding: .3rem .8rem; + color: white; + background-color:black; + cursor: pointer; + font-size: small; + font-family: AnotherAmerica; + letter-spacing:.3rem; + margin-top: 10px; +} +.textContainerpost{ + display: flex; + flex-direction: column; + background-color: #bb2525; + width: 650px; + height: 210px; + border-radius: 2rem; + padding: 15px 15px 6px 15px; + margin: 20px; + border-width: 4px; + border-style:outset; + border-color: black; +} +.opcionesPostContenedor{ + position: absolute; + display: flex; + align-items: center; + margin-top: 145px; + margin-left: 10px; + } +.containerLike{ + align-self: flex-end; + margin: 5px; + width: 60px; + height: 30px; + display: inline-flex; + background-color: black; + border-radius: 100px; + align-items: center; +} +.containerLike:hover{ + transform: scale(1.1); +} +.likeFuego { + width: 20px; + height: 20px; + align-items: center; + margin-left: 10px; +} +.contadorLikes{ + background-position: right; + font-size:large; + font-family: CaviarDreams; + margin-top: 5px; + color: #EB6C36; + align-items: center; +} +.containerPostMenu { + background-color: black; + align-self: center; + width: 140px; + display: flex; + align-items: center; + justify-content: center; + height: 30px; + background-color: black; + border-radius: 100px; + border-style:outset; + border-width: 2px; + border-color:#282828; +} +.eliminarPost { + width: 20px; + height: 20px; + cursor: pointer; + margin-left: 15px; +} +.editarPost { + width: 20px; + height: 20px; + cursor: pointer; +} +.guardarPost { + width: 20px; + height: 20px; + cursor: pointer; + border-radius: 200px; + margin-left: 15px; +} + diff --git a/src/usuario.png b/src/usuario.png new file mode 100644 index 0000000..b718b4c Binary files /dev/null and b/src/usuario.png differ