diff --git a/.eslintrc.json b/.eslintrc.json
index dcd281c..5d16d2d 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -27,6 +27,9 @@
"jest/no-focused-tests": "error",
"jest/no-identical-title": "error",
"jest/prefer-to-have-length": "warn",
- "jest/valid-expect": "error"
+ "jest/valid-expect": "error" ,
+ "import/no-extraneous-dependencies":"off",
+ "no-alert":"off",
+ "arrow-body-style":"off"
}
}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..897af65
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,5 @@
+{
+ "recommendations": [
+ "dbaeumer.vscode-eslint"
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..697809e
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,18 @@
+{
+ "[javascript]": {
+ "editor.maxTokenizationLineLength": 2500,
+ "editor.defaultFormatter": "vscode.typescript-language-features",
+ "editor.tabSize": 2,
+ "editor.formatOnSave": true,
+"editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true,
+}
+ },
+ "[html]": {
+ "editor.suggest.insertMode": "replace",
+ "editor.formatOnSave": true,
+ "editor.defaultFormatter": "vscode.html-language-features"
+ },
+ "editor.detectIndentation": false
+
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index fe12fa3..2204ce9 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
-# Creando una Red Social
+# Creando una Red Social - PET LOVERS
+
+Colaboradoras: Katherine Cevallos, Luz María Vázquez, Ana Karen Morales.
## Índice
diff --git a/babel.config.js b/babel.config.js
index 810987f..f037a1a 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -9,4 +9,4 @@ module.exports = {
},
],
],
-};
\ No newline at end of file
+};
diff --git a/package.json b/package.json
index 1d89e14..e7197ad 100644
--- a/package.json
+++ b/package.json
@@ -15,11 +15,13 @@
"eslint": "eslint --ext .js src/ test/",
"stylelint": "stylelint --aei src/**/*.css",
"pretest": "npm run htmlhint && npm run eslint && npm run stylelint",
- "test": "jest --coverage",
+ "test": "jest --verbose --coverage",
"dev": "vite dev src",
"start": "npm run dev",
"build": "vite build",
- "preview": "vite preview"
+ "preview": "vite preview",
+ "testonly": "jest --verbose --coverage"
+
},
"devDependencies": {
"@babel/preset-env": "^7.19.4",
@@ -28,7 +30,8 @@
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jest": "^25.3.0",
"htmlhint": "^1.0.0",
- "jest": "^27.0.1",
+ "jest": "^27.5.1",
+ "jsdom": "^22.1.0",
"regenerator-runtime": "^0.13.1",
"stylelint": "^14.1.0",
"stylelint-config-recommended": "^6.0.0",
@@ -41,5 +44,10 @@
"createdAt": "2023-06-06T21:37:46.504Z",
"version": "6.3.0",
"commit": "a942adeb868f1fe54b86e34cc4fc4ddb0601700d"
+ },
+ "dependencies": {
+ "@firebase/database": "^0.14.4",
+ "@firebase/firestore": "^3.12.2",
+ "firebase": "^9.22.2"
}
-}
\ No newline at end of file
+}
diff --git a/src/components/feed/feed.controller.js b/src/components/feed/feed.controller.js
new file mode 100644
index 0000000..3b9eb3a
--- /dev/null
+++ b/src/components/feed/feed.controller.js
@@ -0,0 +1,93 @@
+/* eslint-disable max-len */
+/* eslint-disable no-shadow */
+import {
+ collection, addDoc, getFirestore, onSnapshot, doc, deleteDoc, updateDoc, orderBy, query, getDocs, where, arrayUnion, arrayRemove,
+} from 'firebase/firestore';
+import { signOut, getAuth } from 'firebase/auth';
+
+/* import { async } from 'regenerator-runtime'; */
+import { app } from '../../firebase';
+// Se utiliza auth y db para hacer el logout
+const auth = getAuth();
+const db = getFirestore(app);
+// Se exporta función que crea un nuevo documento (post con propiedades) en Firebase
+export const newPost = async ({ publicacion }) => {
+ try {
+ const docRef = await addDoc(collection(db, 'nuevoPost'), {
+ publicacion,
+ createdAt: Date.now(),
+ author: localStorage.getItem('username'), // Le asignamos el autor al post
+ likes: [],
+ });
+
+ console.log('Document written with ID: ', docRef.id);
+ } catch (e) {
+ console.error('Error adding document: ', e);
+ }
+};
+// Función que nos permite visualizar todos los post en tiempo real
+export const subscribeToDataChanges = (actualizarFeed) => {
+ return onSnapshot(query(collection(db, 'nuevoPost'), orderBy('createdAt', 'asc')), (snapshot) => {
+ const data = [];
+ snapshot.forEach((doc) => {
+ data.push({
+ id: doc.id,
+ ...doc.data(),
+ });
+ });
+ actualizarFeed(data);
+ });
+};
+// Función que nos permite cerrar sesión
+export const logoutSesion = async () => {
+ try {
+ const result = await signOut(auth);
+ /* console.log(result); */
+ return (result);
+ // Otras acciones después del cierre de sesión, si las hay...
+ } catch (error) {
+ console.error('Error during logout:', error);
+ throw new Error('Error during logout:');
+ }
+};
+// Función que nos permite eliminar post
+export const deletePost = async (docId) => {
+ /* console.log(docId); */
+ try {
+ await deleteDoc(doc(db, 'nuevoPost', docId));
+ /* console.log(`Documento eliminado: ${docId}`); */
+ } catch (error) {
+ console.error('Error al eliminar el documento:', error);
+ }
+};
+// Función que nos permite guardar los cambios en post editado
+export const updatePost = async (saveId, publicacion) => {
+ return updateDoc(doc(db, 'nuevoPost', saveId), {
+ publicacion,
+ });
+};
+// Función que nos permite guardar en nuestro array el usuario que ya dio like por post o remover
+export const updatePostLike = (id, tipo) => {
+ const email = localStorage.getItem('email');
+ if (tipo === 'union') {
+ return updateDoc(doc(db, 'nuevoPost', id), {
+ likes: arrayUnion(email),
+ });
+ }
+ return updateDoc(doc(db, 'nuevoPost', id), {
+ likes: arrayRemove(email),
+ });
+};
+
+// Consulta para traer un usuario
+export const getDataUser = () => {
+ const q = query(collection(db, 'usuarioPrueba'), where('email', '==', localStorage.getItem('email')));
+ return getDocs(q)
+ .then((querySnapshot) => {
+ /* console.log(querySnapshot); */
+ return querySnapshot.docs[0].data();
+ })
+ .catch((error) => {
+ throw error;
+ });
+};
diff --git a/src/components/feed/feed.js b/src/components/feed/feed.js
new file mode 100644
index 0000000..c526d72
--- /dev/null
+++ b/src/components/feed/feed.js
@@ -0,0 +1,283 @@
+/* import { async } from 'regenerator-runtime'; */
+
+import {
+ newPost, logoutSesion, deletePost, subscribeToDataChanges, updatePost, getDataUser,
+ updatePostLike,
+} from './feed.controller';
+
+const feed = {
+ loadHTML: () => `
+
+ `,
+
+ loadEvents: () => {
+ // Vamos por los datos del usuario cuando carga el feed
+ getDataUser().then((usuario) => {
+ /* Mostrar la imagen y nombre */
+ localStorage.setItem('username', usuario.name);
+ document.getElementById('feedNameProfile').textContent = usuario.name;
+ document.getElementById('feedProfileImage').src = usuario.photoUrl;
+ });
+
+ const clearInput = () => {
+ document.getElementById('feedNewPost').value = '';
+ };
+
+ const logout = document.getElementById('logoutfeed');
+ logout.addEventListener('click', () => {
+ try {
+ logoutSesion(); // Caducar token
+ // Eliminar token
+ localStorage.clear();
+ // Cambiar por : localStorage.clear() Remueve todos los elementos en localStorage.
+ //* / Redireccionamiento del usuario al login
+ window.history.pushState({}, '', `${window.location.origin}/`);
+ window.dispatchEvent(new PopStateEvent('popstate'));
+ } catch (error) {
+ alert.error('Error during logout:', error);
+ }
+ });
+
+ const renderNewElement = (data) => {
+ const feedContainer = document.getElementById('feedScrollContent');
+ const newDiv = document.createElement('div');
+ newDiv.id = 'newPostFeed';
+ const textAreaPub = document.createElement('textarea');
+ textAreaPub.textContent = data.publicacion.publicacion;
+ /* console.log(textAreaPub.textContent); */
+ textAreaPub.id = `ta${data.id}`;
+ // Está deshabilitado hasta que el usuario le de click al ícono editar.
+ textAreaPub.disabled = true;
+
+ const datePost = document.createElement('p');
+ const setDate = new Date(data.publicacion.createdAt);
+ /* console.log(setDate); */
+ const formatoDate = `${setDate.getDate()}/${setDate.getMonth() + 1}/${setDate.getFullYear()}`;
+ datePost.textContent = formatoDate;
+
+ const fotoNombrePost = document.createElement('span');
+ fotoNombrePost.textContent = data.publicacion.author ? data.publicacion.author : 'Usuario Pet Lover';
+
+ const likeEditDeleteDiv = document.createElement('section');
+ likeEditDeleteDiv.id = 'likeEditDelete';
+
+ const contenedorLikes = document.createElement('section');
+
+ const spanLike = document.createElement('span');
+ spanLike.className = 'material-symbols-like';
+ spanLike.textContent = 'favorite';
+ spanLike.id = `li${data.id}`;
+ spanLike.value = data;
+
+ const spanCount = document.createElement('span');
+ spanCount.className = 'material-symbols-count';
+ spanCount.id = `count${data.id}`;
+ spanCount.textContent = data.publicacion.likes.length;
+
+ contenedorLikes.appendChild(spanLike);
+ contenedorLikes.appendChild(spanCount);
+
+ const spanEdit = document.createElement('span');
+ spanEdit.className = 'material-symbols-edit';
+ spanEdit.textContent = 'edit_square';
+ spanEdit.id = `ed${data.id}`;
+ spanEdit.value = data.id;
+
+ const spanDelete = document.createElement('span');
+ spanDelete.className = 'material-symbols-delete';
+ spanDelete.setAttribute('data-id', data.id);
+ spanDelete.textContent = 'delete';
+ spanDelete.id = `de${data.id}`;
+ spanDelete.value = data.id;
+
+ const spanSave = document.createElement('span');
+ spanSave.className = 'material-symbols-save';
+ spanSave.textContent = 'save';
+ spanSave.id = `sa${data.id}`;
+ spanSave.value = data.id;
+ spanSave.style.display = 'none';
+
+ const spanCancel = document.createElement('span');
+ spanCancel.className = 'material-symbols-cancel';
+ spanCancel.textContent = 'cancel';
+ spanCancel.id = `ca${data.id}`;
+ spanCancel.value = data.id;
+ spanCancel.style.display = 'none';
+
+ // likeEditDeleteDiv.appendChild(spanLike);
+ // likeEditDeleteDiv.appendChild(spanCount);
+ likeEditDeleteDiv.appendChild(contenedorLikes);
+ /* - Verficamos si el autor de la publicacion es el mismo del Local Storage - */
+ if (data.publicacion.author === localStorage.getItem('username')) {
+ likeEditDeleteDiv.appendChild(spanEdit);
+ likeEditDeleteDiv.appendChild(spanDelete);
+ }
+
+ likeEditDeleteDiv.appendChild(spanSave);
+ likeEditDeleteDiv.appendChild(spanCancel);
+
+ newDiv.appendChild(fotoNombrePost);
+ newDiv.appendChild(textAreaPub);
+ newDiv.appendChild(likeEditDeleteDiv);
+
+ fotoNombrePost.appendChild(datePost);
+
+ feedContainer.insertBefore(newDiv, feedContainer.firstChild);
+
+ const spanWithLikes = document.getElementById(`li${data.id}`);
+
+ spanWithLikes.addEventListener('click', (event) => {
+ /* const spanCount = document.getElementById(`count${saveId}`); */
+ const likesActuales = event.target.value.publicacion.likes;
+ /* console.log(likesActuales); */
+ const arrayEmail = localStorage.email;
+ const hasLike = likesActuales.includes(arrayEmail);
+
+ if (hasLike) {
+ updatePostLike(event.target.value.id, 'remove');
+ } else {
+ updatePostLike(event.target.value.id, 'union');
+ }
+ });
+
+ spanEdit.addEventListener('click', (e) => {
+ const editId = e.target.value;
+ const textModificado = document.getElementById(`ta${editId}`);
+ // Guardamos temporalmente el origina en el local storage
+ localStorage.setItem('publicacionOriginal', textModificado.value);
+
+ textModificado.disabled = false;
+ textModificado.focus();
+ textModificado.setSelectionRange(textModificado.value.length, textModificado.value.length);
+ document.getElementById(`ed${editId}`).style.display = 'none';
+ document.getElementById(`li${editId}`).style.display = 'none';
+ document.getElementById(`de${editId}`).style.display = 'none';
+ document.getElementById(`sa${editId}`).style.display = 'flex';
+ document.getElementById(`ca${editId}`).style.display = 'flex';
+ });
+
+ spanCancel.addEventListener('click', (e) => {
+ const editId = e.target.value;
+ textAreaPub.disabled = true;
+ document.getElementById(`ed${editId}`).style.display = 'flex';
+ document.getElementById(`li${editId}`).style.display = 'flex';
+ document.getElementById(`de${editId}`).style.display = 'flex';
+ document.getElementById(`sa${editId}`).style.display = 'none';
+ document.getElementById(`ca${editId}`).style.display = 'none';
+ // Recuperamos la publicacion original y lo asignamos al cuadro de texto
+ document.getElementById(`ta${editId}`).value = localStorage.getItem('publicacionOriginal');
+ // Borramos de el local storage
+ localStorage.removeItem('publicacionOriginal');
+ });
+
+ spanSave.addEventListener('click', (e) => {
+ const saveId = e.target.value;
+ const textAreaModificado = document.getElementById(`ta${data.id}`);
+ const publicacionMod = textAreaModificado.value.trim();
+ // Cuando se confirma el guardado simplemente borramos
+ updatePost(saveId, publicacionMod);
+ });
+
+ spanDelete.addEventListener('click', () => {
+ // Crear el modal
+ const modal = document.createElement('div');
+ modal.id = 'modalEliminar';
+ modal.innerHTML = `
+
¿En serio quieres eliminar tu publicación?
+
+
+ `;
+ // Crear el HTML donde el botón de aceptar tenga el id del doc
+ // Agregar el modal al documento
+ document.body.appendChild(modal);
+
+ // Mostrar el modal
+ modal.style.display = 'block';
+
+ // Cerrar el modal al hacer clic en el botón de cancelar
+ const cancelarEliminarBtn = document.getElementById('cancelarEliminar');
+ cancelarEliminarBtn.addEventListener('click', () => {
+ const traerModal = document.getElementById('modalEliminar');
+ traerModal.parentNode.removeChild(traerModal);
+ /* console.log(traerModal); */
+ });
+
+ const aceptarEliminarBtn = document.getElementById('aceptarEliminar');
+ aceptarEliminarBtn.setAttribute('data-id', data.id);
+ aceptarEliminarBtn.addEventListener('click', (event) => {
+ const traerModal = document.getElementById('modalEliminar');
+ traerModal.parentNode.removeChild(traerModal);
+ const docId = event.currentTarget.getAttribute('data-id');
+ /* console.log(docId); */
+ deletePost(docId);
+ });
+ });
+ };
+ // Debo de imprimir en consola el id del doc que debo correr al hacer click
+
+ document.getElementById('publish').addEventListener('click', async () => {
+ const obtenerRelleno = document.getElementById('feedNewPost').value;
+ /* console.log(obtenerRelleno); */
+ if (obtenerRelleno.length !== 0) {
+ await newPost({ publicacion: obtenerRelleno });
+ clearInput(); // Limpia el contenido del campo de entrada
+ }
+ });
+
+ document.getElementById('cancel').addEventListener('click', () => {
+ clearInput();
+ });
+
+ const actualizarFeed = (data) => {
+ const feedContainer = document.getElementById('feedScrollContent');
+ feedContainer.innerHTML = '';
+ data.forEach((item) => {
+ renderNewElement({ publicacion: item, id: item.id });
+ });
+ };
+
+ subscribeToDataChanges(actualizarFeed);
+ },
+};
+
+export default feed;
diff --git a/src/components/login/login.controller.js b/src/components/login/login.controller.js
new file mode 100644
index 0000000..751dc4a
--- /dev/null
+++ b/src/components/login/login.controller.js
@@ -0,0 +1,119 @@
+/* eslint-disable no-underscore-dangle */
+import {
+ addDoc,
+ collection,
+ getDocs,
+ getFirestore,
+ query,
+ where,
+} from 'firebase/firestore';
+
+import {
+ getAuth,
+ GoogleAuthProvider,
+ signInWithEmailAndPassword,
+ signInWithPopup,
+} from 'firebase/auth';
+
+import { app } from '../../firebase';
+
+const db = getFirestore(app);
+const provider = new GoogleAuthProvider();
+const auth = getAuth();
+
+/**
+ * Crea un usuario en la base de datos
+ * @date 16/6/2023 - 10:26:17
+ *
+ * @async
+ * @param {string} name nombre del usuario que inicia sesión
+ * @param {string} email correo del usuario que inicio sesion
+ * @param {string} photoUrl imagen de usuario
+ * @returns {*}
+ */
+export const createUser = (name, email, photoUrl) => {
+ addDoc(collection(db, 'usuarioPrueba'), {
+ name,
+ email,
+ photoUrl,
+ }).catch((error) => {
+ throw error;
+ });
+};
+
+/**
+ * Obtiene un susario de la base de datos por el email
+ * @date 16/6/2023 - 12:22:44
+ *
+ * @async
+ * @param {string} email email del usuario
+ * @returns {Object} El usuario si existe si
+ */
+
+export const getUserByEmail = (email) => {
+ const q = query(collection(db, 'usuarioPrueba'), where('email', '==', email));
+ return getDocs(q)
+ .then((arrayConsulta) => {
+ return arrayConsulta;
+ })
+ .catch((error) => {
+ throw error;
+ });
+};
+
+/**
+ * Inicia el Login con Googl
+ * @date 18/6/2023 - 22:18:00
+ */
+
+export const loginWithGoogle = () => {
+ // Peticion de google para lanzar el modal
+ return signInWithPopup(auth, provider)
+ .then((userCredential) => {
+ // Obtenemos el token y lo guardamos en el Local Storage
+ // const credential = GoogleAuthProvider.credentialFromResult(userCredential);
+ const token = userCredential._tokenResponse.oauthIdToken;
+ localStorage.setItem('accessToken', token);
+
+ // Obtencion de la informacion del usuario que inicio sesion
+ const user = userCredential.user;
+
+ localStorage.setItem('email', userCredential.user.email);
+ // Verificacion si existe el usuario en Firestore si no existe lo creamos
+ return getUserByEmail(user.email)
+ .then((consulta) => {
+ if (consulta.docs.length === 0) {
+ createUser(user.displayName, user.email, user.photoURL);
+ }
+ return true;
+ })
+ .catch((error) => {
+ throw error;
+ });
+ })
+ .catch((error) => {
+ throw error;
+ });
+};
+
+/**
+ * login por usuario y contraseña
+ * @date 21/6/2023 - 16:03:05
+ *
+ * @param {*} email
+ * @param {*} password
+ */
+export const loginWithPassword = (email, password) => {
+ return signInWithEmailAndPassword(auth, email, password)
+ .then((userCredential) => {
+ // Obtenemos el token y el email y lo guardamos en el Local Storage
+ const token = userCredential.user.accessToken;
+ localStorage.setItem('accessToken', token);
+ const mail = userCredential.user.email;
+ localStorage.setItem('email', mail);
+ return true;
+ })
+ .catch((error) => {
+ throw error;
+ });
+};
diff --git a/src/components/login/login.js b/src/components/login/login.js
new file mode 100644
index 0000000..fb3ba34
--- /dev/null
+++ b/src/components/login/login.js
@@ -0,0 +1,92 @@
+import { loginWithGoogle, loginWithPassword } from './login.controller';
+
+const login = {
+ loadHTML: () => `
+
+
+
+

+
+
Inicia sesión
+
+

+
+
O con tu cuenta
+
+
+
+
+
+
+
`,
+
+ loadEvents: () => {
+ /* -------------------------- Navegacion a register ------------------------- */
+ document.getElementById('spnNuevaCuenta').addEventListener('click', () => {
+ window.history.pushState({}, '', `${window.location.origin}/register`);
+ /* ----- Dispara manualmente el evento popstate para actualizar la ruta ----- */
+ window.dispatchEvent(new PopStateEvent('popstate'));
+ });
+ /* ----------------------------- Inniciar sesion con google---------------------------- */
+ document.getElementById('btnLoginGoogle').addEventListener('click', async () => {
+ // Inicio de sesion con google
+ loginWithGoogle()
+ .then(() => {
+ // Redireccionamiento del usuario al feeds
+ window.history.pushState({}, '', `${window.location.origin}/feed`);
+ window.dispatchEvent(new PopStateEvent('popstate'));
+ }).catch(() => {
+ document.getElementById('messageError').style.display = 'block';
+ });
+ });
+
+ /* ----------------- inciar sesion con usuario y contraseña ----------------- */
+
+ document.getElementById('formLogin').addEventListener('submit', (e) => {
+ e.preventDefault();
+ const email = document.getElementById('iptEmail').value;
+ const password = document.getElementById('iptPassword').value;
+
+ loginWithPassword(email, password)
+ .then(() => {
+ // Redireccionamiento del usuario al feeds
+ window.history.pushState({}, '', `${window.location.origin}/feed`);
+ window.dispatchEvent(new PopStateEvent('popstate'));
+ }).catch(() => {
+ document.getElementById('messageError').style.display = 'block';
+ });
+ });
+
+ function ocultarError() {
+ document.getElementById('messageError').style.display = 'none';
+ }
+ document.getElementById('iptEmail').addEventListener('focus', ocultarError);
+ document.getElementById('iptPassword').addEventListener('focus', ocultarError);
+ },
+};
+export default login;
diff --git a/src/components/register/register.controller.js b/src/components/register/register.controller.js
new file mode 100644
index 0000000..31a82c4
--- /dev/null
+++ b/src/components/register/register.controller.js
@@ -0,0 +1,49 @@
+import {
+ getAuth, createUserWithEmailAndPassword,
+} from 'firebase/auth';
+
+import {
+ collection, addDoc, getFirestore,
+
+} from 'firebase/firestore';
+
+import { app } from '../../firebase';
+
+const auth = getAuth();
+
+// Guardamos el nombre, correo y foto para mostrar en el feed
+const db = getFirestore(app);
+export const docRef1 = (nombre, email) => {
+ addDoc(collection(db, 'usuarioPrueba'), {
+ name: nombre,
+ email,
+ photoUrl: 'https://definicion.de/wp-content/uploads/2019/07/perfil-de-usuario.png',
+ });
+};
+
+// Funcion para registrarse por formulario
+export const signInUser = (nombre, email, password) => {
+ createUserWithEmailAndPassword(auth, email, password)
+ .then((userCredential) => {
+ // si se registra correctamente se direcciona al feed tomando el nombre y correo electronico
+ docRef1(nombre, email);
+ const user = userCredential.user;
+ window.history.pushState({}, '', `${window.location.origin}/`);
+ window.dispatchEvent(new PopStateEvent('popstate'));
+
+ console.log(user);
+ })
+ .catch((error) => {
+ // si existe algun error aparecen errores si el email ya se encuentra registrado,
+ // o si tiene mas de 6 caracteres
+ const errorCode = error.code;
+
+ if (errorCode === 'auth/email-already-in-use') {
+ document.getElementById('repeat-email').style.display = 'block';
+ } else if (errorCode === 'auth/weak-password') {
+ document.getElementById('6-letters').style.display = 'block';
+ } else {
+ document.getElementById('7-letter').style.display = 'block';
+ }
+ });
+};
diff --git a/src/components/register/register.js b/src/components/register/register.js
new file mode 100644
index 0000000..a00221b
--- /dev/null
+++ b/src/components/register/register.js
@@ -0,0 +1,104 @@
+// import { crearUsuario } from './register.controller';
+
+import { signInUser } from './register.controller';
+import { loginWithGoogle } from '../login/login.controller';
+
+const register = {
+ loadHTML: () => `
+
+
+
Bienvenidos a:
+

+
Somos un espacio en donde podrás consultar o publicar información acerca de
+ nuestros amigos de 4
+ patitas
+
+
+
+
+
+
+ `,
+ loadEvents: () => {
+ document.getElementById('formCrearcuenta').addEventListener('submit', (event) => {
+ // para que no se recargue la pagina
+ event.preventDefault();
+ // Tomamos los valores de los inputs nombre, correo, contrasena y confirmar contrasena
+ const nombre = document.getElementById('nombre').value;
+ const email = document.getElementById('correo').value;
+ const contrasena = document.getElementById('contrasena').value;
+ const confirmarContrasena = document.getElementById('confirmar-contrasena').value;
+
+ if (contrasena === confirmarContrasena) {
+ // si la contrasena coincide con el confirmar contrasena continua con la funcion signuser
+ // como no tiene guardado el token se redirecciona a login
+ signInUser(nombre, email, contrasena);
+ } else {
+ // si no coinciden aparece un mensaje de error
+ document.getElementById('repeat-password').style.display = 'block';
+ }
+ });
+
+ /* -------------------------- Navegacion a login ------------------------- */
+ /* Si da clic en que tiene ya una cuenta registrada le redirecciona a Login */
+ document.getElementById('spnRegistro').addEventListener('click', () => {
+ window.history.pushState({}, '', `${window.location.origin}/`);
+ /* ----- Dispara manualmente el evento popstate para actualizar la ruta ----- */
+ window.dispatchEvent(new PopStateEvent('popstate'));
+ });
+ /* ----------------------------- Iniciar sesion con google---------------------------- */
+ /* Al momento de dar clic en el icono Google se dispara la funcion de Google LoginWithGoogle
+ Se encuentra en login.controller.js */
+ document.getElementById('btnLoginGoogle').addEventListener('click', async () => {
+ document.getElementById('btnLoginGoogle').disabled = true;
+ // Inicio de sesion con google
+ loginWithGoogle()
+ .then(() => {
+ // Redireccionamiento del usuario al feeds
+ window.history.pushState({}, '', `${window.location.origin}/feed`);
+ window.dispatchEvent(new PopStateEvent('popstate'));
+ }).catch(() => {
+ document.getElementById('messageError').style.display = 'block';
+ });
+ });
+
+ function ocultarError() {
+ /* Al momento de dar clic en cualquiera de los inputs desaparecen los mensajes de error */
+ document.getElementById('repeat-password').style.display = 'none';
+ document.getElementById('repeat-email').style.display = 'none';
+ document.getElementById('6-letters').style.display = 'none';
+ document.getElementById('7-letters').style.display = 'none';
+ }
+ document.getElementById('correo').addEventListener('focus', ocultarError);
+ document.getElementById('contrasena').addEventListener('focus', ocultarError);
+ document.getElementById('confirmar-contrasena').addEventListener('focus', ocultarError);
+ document.getElementById('nombre').addEventListener('focus', ocultarError);
+ },
+};
+
+export default register;
diff --git a/src/firebase.js b/src/firebase.js
new file mode 100644
index 0000000..5a388bf
--- /dev/null
+++ b/src/firebase.js
@@ -0,0 +1,14 @@
+/* eslint-disable import/no-extraneous-dependencies */
+import { initializeApp } from 'firebase/app';
+
+const firebaseConfig = {
+ apiKey: 'AIzaSyBcKxh-RAJ5tbkvevJz7JJLlJXeLUJqfiU',
+ authDomain: 'pet-lovers-a0c33.firebaseapp.com',
+ projectId: 'pet-lovers-a0c33',
+ storageBucket: 'pet-lovers-a0c33.appspot.com',
+ messagingSenderId: '348333556906',
+ appId: '1:348333556906:web:83992e5ad022fa6e917cd3',
+ measurementId: 'G-D0TZTYL4PJ',
+};
+// Initialize Firebase
+export const app = initializeApp(firebaseConfig);
diff --git a/src/firebase/function_firebase.js b/src/firebase/function_firebase.js
new file mode 100644
index 0000000..c23d6a5
--- /dev/null
+++ b/src/firebase/function_firebase.js
@@ -0,0 +1,19 @@
+// import { auth } from "./firebase";
+import { getAuth, createUserWithEmailAndPassword } from 'firebase/auth';
+import { app } from '../firebase';
+
+export const createUser = (email, contrasena) => {
+ const auth = getAuth(app);
+ createUserWithEmailAndPassword(auth, email, contrasena)
+ .then((userCredential) => {
+ // Signed in
+ const user = userCredential.user;
+ console.log(user);
+ // ...
+ })
+ .catch((error) => {
+ const errorCode = error.code;
+ const errorMessage = error.message;
+ console.log(errorCode, errorMessage);
+ });
+};
diff --git a/src/img/feed.PNG b/src/img/feed.PNG
new file mode 100644
index 0000000..746ad12
Binary files /dev/null and b/src/img/feed.PNG differ
diff --git a/src/img/google-removebg-preview.png b/src/img/google-removebg-preview.png
new file mode 100644
index 0000000..e1a82eb
Binary files /dev/null and b/src/img/google-removebg-preview.png differ
diff --git a/src/img/google.png b/src/img/google.png
new file mode 100644
index 0000000..494aced
Binary files /dev/null and b/src/img/google.png differ
diff --git a/src/img/image-huella-naranja.png b/src/img/image-huella-naranja.png
new file mode 100644
index 0000000..b576232
Binary files /dev/null and b/src/img/image-huella-naranja.png differ
diff --git a/src/img/image-huellitas.png b/src/img/image-huellitas.png
new file mode 100644
index 0000000..b5b018d
Binary files /dev/null and b/src/img/image-huellitas.png differ
diff --git a/src/img/image-removebg-preview.png b/src/img/image-removebg-preview.png
new file mode 100644
index 0000000..bd95a99
Binary files /dev/null and b/src/img/image-removebg-preview.png differ
diff --git a/src/img/log-in.PNG b/src/img/log-in.PNG
new file mode 100644
index 0000000..41f7df1
Binary files /dev/null and b/src/img/log-in.PNG differ
diff --git a/src/img/logo.jpg b/src/img/logo.jpg
new file mode 100644
index 0000000..235f4eb
Binary files /dev/null and b/src/img/logo.jpg differ
diff --git a/src/img/logo.png b/src/img/logo.png
new file mode 100644
index 0000000..bd95a99
Binary files /dev/null and b/src/img/logo.png differ
diff --git a/src/img/register.PNG b/src/img/register.PNG
new file mode 100644
index 0000000..3f0ed42
Binary files /dev/null and b/src/img/register.PNG differ
diff --git a/src/imgfeed/abejita.png b/src/imgfeed/abejita.png
new file mode 100644
index 0000000..942166c
Binary files /dev/null and b/src/imgfeed/abejita.png differ
diff --git a/src/imgfeed/logo-corto.png b/src/imgfeed/logo-corto.png
new file mode 100644
index 0000000..4c14d75
Binary files /dev/null and b/src/imgfeed/logo-corto.png differ
diff --git a/src/imgfeed/logo-eslogan.png b/src/imgfeed/logo-eslogan.png
new file mode 100644
index 0000000..fb3ae48
Binary files /dev/null and b/src/imgfeed/logo-eslogan.png differ
diff --git a/src/imgfeed/perfilFoto.jpg b/src/imgfeed/perfilFoto.jpg
new file mode 100644
index 0000000..599a8dd
Binary files /dev/null and b/src/imgfeed/perfilFoto.jpg differ
diff --git "a/src/imgfeed/perfilvac\303\255o.PNG" "b/src/imgfeed/perfilvac\303\255o.PNG"
new file mode 100644
index 0000000..83670c2
Binary files /dev/null and "b/src/imgfeed/perfilvac\303\255o.PNG" differ
diff --git a/src/imgfeed/perritove.png b/src/imgfeed/perritove.png
new file mode 100644
index 0000000..d230970
Binary files /dev/null and b/src/imgfeed/perritove.png differ
diff --git a/src/index.html b/src/index.html
index 788db3c..6da2e5a 100644
--- a/src/index.html
+++ b/src/index.html
@@ -1,12 +1,24 @@
+
-
-
-
- Document
+
+
+
+ Document
+
+
+
+
+
+
+
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/src/lib/index.js b/src/lib/index.js
deleted file mode 100644
index d193089..0000000
--- a/src/lib/index.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// aqui exportaras las funciones que necesites
-
-export const myFunction = () => {
- // aqui tu codigo
- console.log('Hola mundo!');
-};
diff --git a/src/main.js b/src/main.js
index ac27e91..93cc2c0 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,5 +1,51 @@
-// Este es el punto de entrada de tu aplicacion
+import { routes } from './routes.js';
-import { myFunction } from './lib/index.js';
+// Funcion para navegar entre componentes
+export const navigation = (path) => {
+ const root = document.getElementById('app');
+ // Buscamos que componente corresponde a la ruta en el objeto routes
+ const component = routes[path];
+ // Cargamos el HTML
+ root.innerHTML = component.loadHTML();
+ // Cargamos los eventos
+ component.loadEvents();
+};
-myFunction();
+// Evento al cargar la pagina
+window.addEventListener('load', () => {
+ let path = window.location.pathname;
+ const token = localStorage.getItem('accessToken');
+
+ if (path === '/' || path === '/register') {
+ // Para ir al login o register no debe haber token
+ if (token !== null) {
+ path = '/feed';
+ window.location.pathname = path;
+ }
+ } else if (path === '/feed') {
+ if (token === null) {
+ path = '/';
+ window.location.pathname = path;
+ }
+ }
+ navigation(path);
+});
+
+// Evento al cambiar la ruta
+window.addEventListener('popstate', () => {
+ let path = window.location.pathname;
+ const token = localStorage.getItem('accessToken');
+
+ if (path === '/' || path === '/register') {
+ if (token !== null) {
+ path = '/feed';
+ window.location.pathname = path;
+ }
+ } else if (path === '/feed') {
+ if (token === null) {
+ path = '/';
+ window.location.pathname = path;
+ }
+ }
+ navigation(path);
+});
diff --git a/src/routes.js b/src/routes.js
new file mode 100644
index 0000000..bfab97c
--- /dev/null
+++ b/src/routes.js
@@ -0,0 +1,9 @@
+import feed from './components/feed/feed';
+import login from './components/login/login';
+import register from './components/register/register';
+
+export const routes = {
+ '/': login,
+ '/register': register,
+ '/feed': feed,
+};
diff --git a/src/styles.css b/src/styles.css
new file mode 100644
index 0000000..4cc5aea
--- /dev/null
+++ b/src/styles.css
@@ -0,0 +1,995 @@
+@import url('https://fonts.googleapis.com/css2?family=Inconsolata&family=Montserrat:wght@300&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Inconsolata&family=Montserrat:wght@500&display=swap');
+body{
+ height: 100%;
+ margin: 0;
+ font-family: 'Arial';
+ background-color: #fafafa;
+}
+.fondo-naranja {
+ background-color: #F39F25;
+}
+/* --------------------- Definicion de tamaños de letra --------------------- */
+.text-small {
+ font-size: small;
+}
+.text-medium {
+ font-size: medium;
+}
+.text-large{
+ font-size: larger;
+}
+.text-title{
+ color: #333333;
+ font-size: 25px;
+ font-weight: 500;
+ margin: 5px;
+
+}
+.text-color-white{
+color: #ffffff;
+}
+.text-color-orange{
+ color: #FFA500;
+}
+
+.manita{
+ cursor: pointer;
+}
+
+
+
+
+/* -------------------------------------------------------------------------- */
+/* Clases Login */
+/* -------------------------------------------------------------------------- */
+
+.l-div{
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+.l-container{
+ height: 100%;
+ display: flex;
+ padding: 80px;
+
+}
+
+.l-container-login{
+max-width: 400px;
+min-width: 350px;
+display: flex;
+flex-direction: column;
+background-color: #fff;
+text-align: center;
+padding-top: 2em;
+box-shadow: 0px 4px 4px 4px rgba(0, 0, 0, 0.25);
+border-radius: 20px 0px 0px 20px;
+gap: 0.5em;
+}
+.l-container-form{
+ display: flex;
+ flex-direction: column;
+ margin: 0em 3em 3em 3em;
+}
+.l-container-informacion{
+ max-width: 400px;
+padding: 1em;
+text-align: center;
+/* background: rgba(243, 237, 206, 0.33); */
+background: #FFA500;
+box-shadow: 4px 4px 4px 0px rgba(0, 0, 0, 0.25);
+border-radius: 0px 20px 20px 0px;
+}
+img{
+ max-width: 300px;
+}
+.imgResponsive{
+ display:none;
+}
+.l-input-with-icon {
+ position: relative;
+ display: inline-block;
+ margin-bottom: 1em;
+}
+
+.l-input-with-icon i {
+ position: absolute;
+ right: 5px; /* Ajusta el valor según sea necesario */
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+.l-input-with-icon input {
+ /* padding-right: 30px; Ajusta el valor según sea necesario */
+ border: none;
+ border-bottom: 1px solid #B8B8B8;
+ outline: none;
+ font-size: medium;
+ width: 100%; /* Establece el ancho al 100% del contenedor */
+
+}
+
+
+.l-titulo-info{
+ color: #fff;
+}
+.l-button-login{
+mix-blend-mode: normal;
+border-radius: 50px;
+width: 180px;
+height: 50px;
+left: 115px;
+top: 579px;
+
+font-size: medium;
+border: #FFA500 solid 1px;
+ background-color: #FFFFFF;
+ color: #FFA500;
+
+}
+
+.l-button-login:hover {
+ background-color: #FFA500;
+
+ border: none;
+ color: #FFFFFF;
+ cursor: pointer;
+}
+
+@media only screen and (max-width: 800px) {
+ .l-container-informacion {
+ display: none;
+ }
+ .l-container-login{
+ border-radius: 20px 20px 20px 20px;
+ }
+ .imgResponsive{
+ display:block;
+ margin-left: auto;
+ margin-right: auto;
+ max-width: 150px;
+
+
+ }
+ .text-title{
+ padding-bottom: 0px !important; }
+ }
+
+
+
+/* -------------------------------------------------------------------------- */
+/* Clases feed */
+
+/* -------------------------------------------------------------------------- */
+
+
+
+
+@media only screen and (min-width: 20px) {
+
+ body#bodyApp {
+ /* background-image: url(img/image-huella-naranja.png); */
+ background-color: rgba(250, 235, 215, 0.655);
+
+ }
+
+#pageAllContent {
+ width: 100%;
+ max-width: 1000px;
+ margin: 0 auto;
+ overflow: hidden;
+}
+
+#feedHeader {
+ width: 100%;
+ height: 60px;
+ background-color: #f39f25;
+ border-top: 3px solid #f39f25;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ border-bottom: 5px solid #CD3B32;
+}
+
+#feedLogoContent {
+ width: 10%;
+}
+
+img#feedLogo {
+ width: 100px;
+ height: 55px;
+ background: cover;
+ margin: 0%;
+ display: flex;
+ align-items: center;
+ filter: brightness(100%);
+ padding:0 10px;
+}
+
+nav#feedGeneralSearch {
+ width: 30%;
+ display: flex;
+ align-items: center;
+ padding: 10px 5px;
+}
+
+#searchContent {
+ width: 15%;
+ height: 100%;
+ background-color: #CD3B32;
+ border: 1px solid #CD3B32;
+ border-radius: 0 4px 4px 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+input#inputSearch {
+ width: 85%;
+ height: 100%;
+ background-color: rgba(255, 235, 205, 0.797);
+ border-radius: 4px 0 0 4px;
+ border: none;
+}
+
+span.material-symbols-search {
+ color: aliceblue;
+ font-family: 'Arial';
+ font-size: 20px;
+}
+
+span.material-symbols-outlined {
+ padding: 5px;
+ font-family: 'Material Symbols Outlined', sans-serif;
+ font-size: 30px;
+ display: flex;
+ align-items: center;
+ filter: brightness(100%);
+ cursor: pointer;
+}
+
+#feedAllContent {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ background-color: rgb(250, 235, 215);
+
+
+}
+
+#feedAside {
+ width: 25%;
+ height: auto;
+ background-color: rgb(250, 235, 215);
+ margin: 0 0 10px 0;
+ display: flex;
+ flex-direction: column;
+ align-items: start;
+ }
+
+#feedMenu {
+ width: 95%;
+ height: auto;
+ display: flex;
+ justify-content: end;
+ padding: 5px 0 5px 0;
+ margin: 5px 0 10px 0;
+}
+
+span.material-symbols-menu {
+ padding: 5px;
+ font-family: 'Material Symbols Outlined', sans-serif;
+ font-size: 30px;
+ color: #CD3B32;
+}
+
+#feedProfile {
+ width: 90%;
+ height: auto;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+}
+
+#feedProfileImageContent {
+ width: 80%;
+ height: auto;
+ border-radius: 50%;
+ overflow: hidden;
+ display: flex;
+ justify-content: center;
+}
+
+#feedProfileImage {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ object-position: center;
+}
+
+
+#feedNameProfile {
+ margin: 10px 10px;
+ font-size: 20px;
+ text-align: center;
+}
+
+.feedNameLogo {
+ color: #CD3B32;
+ font-size: 20px;
+ font-family: 'Arial';
+ font-weight: 400;
+}
+
+#feedIntroduction {
+ width: 75%;
+ height: auto;
+ text-align: center;
+ margin: 10px 10px;
+}
+
+section#feedScroll {
+ width: 95%;
+ min-height: 2000px;
+ margin: 0 0 0 5px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ /* border-radius: 5px 0 5px 5px; */
+ background-color: rgba(250, 235, 215, 0.5);
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ box-shadow: -5px 0 5px rgba(0, 0, 0, 0.2), 5px 0 5px rgba(0, 0, 0, 0.2), 0 2px 4px rgba(0, 0, 0, 0.2);
+
+}
+
+div#feedScrollContent {
+ width: 95%;
+ margin: 0 0 50px 0;
+}
+
+section#newPost {
+ width: 95%;
+ height: auto;
+ background-color:#f3a1257e;
+ border-radius: 8px;
+ margin: 10px 0 10px 0;
+ /* padding: 10px 10px; */
+ display: flex;
+ flex-direction: column;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+
+#feedScrollContent textarea {
+ border: none;
+ background-color: #ffffff33;
+ width: 98%;
+ min-height: 100px;
+ border-radius: 8px;
+ resize: none;
+ font-size: 16px;
+ font-family:'Arial';
+ /* font-weight: bold; */
+ margin: 10px 5px;
+ box-sizing: border-box;
+ padding: 15px 15px;
+}
+
+
+#feedScrollContent div {
+ width: 100%;
+ height: auto;
+ background-color:#f3a1257e;
+ border-radius: 8px;
+ box-sizing: border-box;
+ margin: 20px 0 20px 0;
+ padding: 10px 10px;
+ display: flex;
+ flex-direction: column;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+
+#feedScrollContent div span {
+ position: relative;
+ width: 100%;
+ min-height: 20px;
+ display: flex;
+ flex-direction: row;
+ font-size: 16px;
+ font-weight: bold;
+ box-sizing: border-box;
+ padding: 10px;
+}
+
+input#feedNewPost {
+ width: 93%;
+ height: 50px;
+ background-color: #ffffff45;
+ border-radius: 8px;
+ border: none;
+ margin: 10px 10px;
+ padding: 10px 10px;
+ display: flex;
+ align-items: flex-start;
+ text-align: left;
+}
+
+.newPost {
+ font-size: 16px;
+ font-weight: bolder;
+ font-family: 'Arial';
+ color: #CD3B32;
+ display: flex;
+ align-items: end;
+ margin-top: 10px;
+ margin-bottom: 0;
+}
+
+.botones {
+ width: 95%;
+ height: auto;
+ display: flex;
+ justify-content: end;
+ margin-bottom: 10px;
+}
+
+#publish,
+#cancel {
+ margin:5px 5px;
+ border-radius: 7px;
+ background-color: #CD3B32;
+ border: none;
+ padding: 5px 5px;
+ font-size: 14px;
+ color: aliceblue;
+ cursor: pointer;
+}
+
+#feedNewPost::placeholder {
+ font-size: 16px;
+ font-weight: lighter;
+}
+
+div#randomImages {
+ width: 100%;
+ height: 200px;
+ background-color: antiquewhite;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+ border-bottom: solid 5px #010101;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+
+#adoptionLetter {
+ width: 40%;
+ font-family: 'Indie Flower', cursive;
+ font-weight: bolder;
+ font-size: 25px;
+ color: #CD3B32;
+ text-align: center;
+ margin: 20px 40px 20px 40px;
+ display: flex;
+ align-items: center;
+}
+
+.randomAbeja {
+ width: 20%;
+ padding: 10px 0;
+}
+
+img#randomAbeja {
+ width: 100%;
+ height: 100px;
+ object-fit: cover;
+}
+
+.randomDog {
+ width: 40%;
+ display: flex;
+ justify-content: center;
+}
+
+img#randomDog {
+ width: 100%;
+ height: 300px;
+ object-fit: cover;
+ z-index: 1;
+}
+
+#feedScrollContent {
+ width: 90%;
+ height: auto;
+ background-color:antiquewhite;
+ margin: 10px 0 10px 0;
+ border-radius: 8px;
+}
+
+section#likeEditDelete {
+ width: 100%;
+ height: auto;
+ display: flex;
+ justify-content: flex-center;
+ padding: 10px 10px;
+}
+
+span.material-symbols-like,
+span.material-symbols-edit,
+span.material-symbols-delete,
+span.material-symbols-save,
+span.material-symbols-cancel {
+ color: rgb(0, 0, 0);
+ font-family: 'Material Symbols Outlined', sans-serif;
+ font-size: 30px;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ cursor: pointer;
+}
+
+span.material-symbols-like,
+span.material-symbols-count,
+span.material-symbols-edit,
+span.material-symbols-delete {
+ font-size: 40px;
+ display: flex;
+ justify-content: center;
+ }
+
+
+
+#feedScrollContent p {
+ position: absolute;
+ background-color:#f3a12500;
+ width: 95%;
+ height: auto;
+ font-size: 12px;
+ text-align: end;
+ padding: 0;
+ margin: 2px 10px 10px 10px;
+}
+
+div#modalEliminar {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background-color: #fff;
+ border-radius: 4px;
+ padding: 20px;
+ box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
+ z-index: 9999;
+ font-size: 12px;
+ text-align: center;
+ }
+
+ #cancelarEliminar,
+ #aceptarEliminar {
+ margin:5px 5px;
+ border-radius: 7px;
+ background-color: #CD3B32;
+ border: none;
+ padding: 5px 5px;
+ font-size: 12px;
+ color: aliceblue;
+ }
+}
+
+@media only screen and (max-width: 281px){
+ #feedLogoContent {
+ width: 10%;
+ }
+
+ img#feedLogo {
+ width: 70px;
+ height: 50px;
+ }
+
+ #feedHeader {
+ height: 50px;
+ }
+
+ .randomAbeja {
+ display: none;
+ }
+
+ img#randomAbeja {
+ display: none;
+ }
+
+ span.material-symbols-outlined {
+ font-size: 18px;
+ }
+
+ #feedProfileImageContent {
+ width: 30%;
+ }
+}
+
+@media only screen and (max-width: 767px){
+ span.material-symbols-menu {
+ padding: 1px;
+ font-size: 20px;
+ }
+
+ #feedProfileImageContent {
+ width: 60%;
+ }
+
+ #feedNameProfile {
+ margin: 10px 10px;
+ font-size: 12px;
+ }
+
+ #feedWelcome {
+ font-size: 12px;
+ }
+
+ #feedIntroduction {
+ font-size: 12px;
+ }
+
+ .feedNameLogo {
+ font-size: 16px;
+ }
+
+ div#randomImages {
+ height: 105px;
+ }
+
+ #adoptionLetter {
+ font-size: 16px;
+ margin: 10px 20px 10px 20px;
+ }
+
+ .randomAbeja {
+ padding: 15px;
+ }
+
+ img#randomAbeja {
+ height: 60px;
+
+ }
+
+ img#randomDog {
+ height: 160px;
+ }
+
+ section#newPost {
+ width: 95%;
+ }
+
+ input#feedNewPost {
+ width: 90%;
+ }
+
+ .newPost {
+ font-size: 12px;
+ }
+
+ .botones {
+ width: 90%;
+ }
+
+ #feedcategory,
+ #publish,
+ #cancel {
+ margin:3px 3px;
+ font-size: 10px;
+ }
+
+ #feedScrollContent {
+ width: 90%;
+ margin: 0;
+ border-radius: 8px;
+ }
+
+ #feedNewPost::placeholder {
+ font-size: 12px;
+ font-weight: lighter;
+ }
+
+ div#modalEliminar {
+ padding: 10px;
+ }
+
+ #feedScrollContent p {
+ font-size: 12px;
+ }
+
+ #feedScrollContent div span {
+ font-size: 14px;
+ }
+
+ span.material-symbols-like,
+span.material-symbols-edit,
+span.material-symbols-delete {
+ font-size: 16px;
+}
+
+span.material-symbols-outlined {
+ font-size: 20px;
+}
+}
+
+@media only screen and (max-width: 480px) {
+ #feedAllContent {
+ flex-direction: column;
+ }
+
+ #feedAside {
+ width: 100%;
+ height: 100%;
+ }
+
+ #feedScroll {
+ width: 100%;
+ }
+
+ #feedIntroduction {
+ display: none;
+ }
+
+ #feedProfile {
+ flex-direction: row;
+ justify-content: flex-start;
+ margin-bottom: 10px;
+ margin-left: 20px;
+ }
+
+ #feedProfileImageContent {
+ width: 20%;
+ }
+
+ #feedNameProfile {
+ margin: 10px 10px;
+ font-size: 16px;
+ }
+
+ #feedWelcome {
+ display: none;
+ }
+
+ #feedMenu {
+ padding: 1px 0 1px 0;
+ margin: 1px 0 1px 0;
+ }
+
+ span.material-symbols-menu {
+ padding: 1px;
+ }
+
+ #feedLogoContent {
+ width: 30%;
+ }
+
+ div#randomImages {
+ height: 105px;
+ }
+
+ #adoptionLetter {
+ font-size: 16px;
+ margin: 10px 20px 10px 20px;
+ }
+
+ .randomAbeja {
+ padding: 15px;
+ }
+
+ img#randomAbeja {
+ height: 60px;
+
+ }
+
+ img#randomDog {
+ height: 160px;
+ }
+
+ section#newPost {
+ width: 100%;
+ }
+
+ input#feedNewPost {
+ width: 90%;
+ }
+
+ .newPost {
+ font-size: 12px;
+ }
+
+ .botones {
+ width: 90%;
+ }
+
+ #feedcategory,
+ #publish,
+ #cancel {
+ margin:3px 3px;
+ font-size: 10px;
+ }
+
+ #feedScrollContent {
+ width: 100%;
+ margin: 0;
+ border-radius: 8px;
+ }
+
+ #feedNewPost::placeholder {
+ font-size: 12px;
+ font-weight: lighter;
+ }
+
+ div#modalEliminar {
+ padding: 10px;
+ }
+
+ #feedScrollContent p {
+ font-size: 12px;
+ }
+
+ span.material-symbols-like,
+span.material-symbols-edit,
+span.material-symbols-delete {
+ font-size: 16px;
+
+}
+
+span.material-symbols-outlined {
+ font-size: 20px;
+}
+}
+
+
+
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+/* Register */
+/* -------------------------------------------------------------------------- */
+
+
+
+section{
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ /*background-image: url(img/image-huella-naranja.png);*/
+}
+.contenedor-crear-cuenta{
+ height: 100%;
+ display: flex;
+ padding: 80px;
+}
+
+.formulario-cuenta{
+ max-width: 400px;
+ display: flex;
+ flex-direction: column;
+background-color: #fff;
+text-align: center;
+padding: 3em;
+box-shadow: 0px 4px 4px 4px rgba(0, 0, 0, 0.25);
+border-radius: 0px 20px 20px 0px;
+}
+
+.logo-cuenta{
+ max-width: 400px;
+padding: 1em;
+text-align: center;
+/* background: rgba(243, 237, 206, 0.33); */
+background: #FFA500;
+box-shadow: 4px 4px 4px 0px rgba(0, 0, 0, 0.25);
+border-radius: 20px 0px 0px 20px;
+}
+.marca{
+ max-width: 300px;
+}
+
+.ingresa {
+ position: relative;
+ display: inline-block;
+ padding-right: 30px; /* Ajusta el valor según sea necesario */
+ border: none;
+ border-bottom: 1px solid #B8B8B8;
+ outline: none;
+ font-size: medium;
+ margin-top: 5%;
+}
+
+
+.ingresa input {
+ padding-right: 30px; /* Ajusta el valor según sea necesario */
+ border: none;
+ border-bottom: 1px solid #B8B8B8;
+ outline: none;
+ font-size: medium;
+}
+
+
+
+#Crearcuenta {
+mix-blend-mode: normal;
+border-radius: 50px;
+width: 180px;
+height: 50px;
+font-size: medium;
+border: #CD3B32 solid 1px;
+background-color: #FFFFFF;
+color: #CD3B32;
+margin-top: 30px;
+margin-left: 20%;
+margin-bottom: 30px;
+box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
+}
+
+#Crearcuenta:hover {
+ background-color: #CD3B32;
+ border: none;
+ color: #FFFFFF;
+ cursor: pointer;
+}
+
+#Google {
+ height: 60px;
+ width: 60px;
+ filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25));
+ margin-top: 30px;
+ margin-left: 40%;
+}
+
+#Google:hover {
+ cursor: pointer;
+
+}
+
+.text-title{
+ padding-bottom: 25px ;
+}
+
+#bienvenido {
+ margin-top: 40px;
+}
+
+h1 {
+ text-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
+}
+
+#distintas-contrasenas {
+ font-size: large;
+ color: #000000;
+ font-weight: 700;
+
+}
+
+.imgResponsive{
+ display: none;
+}
+
+@media only screen and (max-width: 800px) {
+ .logo-cuenta {
+ display: none;
+ }
+ .formulario-cuenta {
+ border-radius: 20px 20px 20px 20px;
+ }
+ .imgResponsive{
+ display:block;
+ margin-left: auto;
+ margin-right: auto;
+ max-width: 150px;
+
+
+ }
+ .text-title{
+ padding-bottom: 0px !important; }
+ }
+
+
diff --git a/test/feed.spec.js b/test/feed.spec.js
new file mode 100644
index 0000000..6587b31
--- /dev/null
+++ b/test/feed.spec.js
@@ -0,0 +1,184 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import feed from '../src/components/feed/feed';
+import {
+ newPost, subscribeToDataChanges, logoutSesion, deletePost, updatePost, updatePostLike,
+ getDataUser,
+} from '../src/components/feed/feed.controller';
+
+describe('Feed test header', () => {
+ test('Content of elements in header', () => {
+ // Preparación
+ const app = document.createElement('header');
+ // Ejecucion con los actores: Aquí cargamos el HTML en el contenedor
+ app.innerHTML = feed.loadHTML();
+ // Aserción: Comprobamos la existencia de elementos específicos
+ const header = app.querySelector('#feedHeader');
+ expect(header).not.toBeNull();
+
+ const logo = app.querySelector('#feedLogo');
+ expect(logo).not.toBeNull();
+
+ const logout = app.querySelector('#logoutfeed');
+ expect(logout).not.toBeNull();
+ });
+});
+
+describe('Feed test section feedAllContent', () => {
+ test('Content of elements in feedAllContent', () => {
+ // Preparación
+ const app = document.createElement('section');
+ // Ejecucion con los actores: Aquí cargamos el HTML en el contenedor
+ app.innerHTML = feed.loadHTML();
+ // Aserción: Comprobamos la existencia de elementos específicos
+ const asideProfile = app.querySelector('#feedAside');
+ expect(asideProfile).not.toBeNull();
+
+ const feedScroll = app.querySelector('#feedScroll');
+ expect(feedScroll).not.toBeNull();
+ });
+});
+
+describe('Feed test aside for profile', () => {
+ test('Content of elements in aside', () => {
+ // Preparación
+ const app = document.createElement('aside');
+ // Ejecucion con los actores: Aquí cargamos el HTML en el contenedor
+ app.innerHTML = feed.loadHTML();
+ // Aserción: Comprobamos la existencia de elementos específicos
+ const imageProfile = app.querySelector('#feedProfileImage');
+ expect(imageProfile).not.toBeNull();
+
+ const nameProfile = app.querySelector('#feedNameProfile');
+ expect(nameProfile).not.toBeNull();
+
+ const welcome = app.querySelector('#feedWelcome');
+ expect(welcome).not.toBeNull();
+
+ const feedIntroduction = app.querySelector('#feedIntroduction');
+ expect(feedIntroduction).not.toBeNull();
+ });
+});
+
+describe('Feed test feedScroll', () => {
+ test('Content of elements in feedScroll', () => {
+ // Preparación
+ const app = document.createElement('section');
+ // Ejecucion con los actores: Aquí cargamos el HTML en el contenedor
+ app.innerHTML = feed.loadHTML();
+ // Aserción: Comprobamos la existencia de elementos específicos
+ const randomImages = app.querySelector('#randomImages');
+ expect(randomImages).not.toBeNull();
+
+ const newPostSection = app.querySelector('#newPost');
+ expect(newPostSection).not.toBeNull();
+
+ const feedScrollContent = app.querySelector('#feedScrollContent');
+ expect(feedScrollContent).not.toBeNull();
+ });
+});
+
+describe('Feed test feedRandomImages', () => {
+ test('Content of elements in randomImages', () => {
+ // Preparación
+ const app = document.createElement('div');
+ // Ejecucion con los actores: Aquí cargamos el HTML en el contenedor
+ app.innerHTML = feed.loadHTML();
+ // Aserción: Comprobamos la existencia de elementos específicos
+ const adoptionLetter = app.querySelector('#adoptionLetter');
+ expect(adoptionLetter).not.toBeNull();
+
+ const randomAbeja = app.querySelector('#randomAbeja');
+ expect(randomAbeja).not.toBeNull();
+
+ const randomDog = app.querySelector('#randomDog');
+ expect(randomDog).not.toBeNull();
+ });
+});
+
+describe('Feed test newPost section', () => {
+ test('Content of elements in newPost section', () => {
+ // Preparación
+ const app = document.createElement('section');
+ // Ejecucion con los actores: Aquí cargamos el HTML en el contenedor
+ app.innerHTML = feed.loadHTML();
+ // Aserción: Comprobamos la existencia de elementos específicos
+ const newPostParagraph = app.querySelector('.newPost');
+ expect(newPostParagraph).not.toBeNull();
+
+ const newPostInput = app.querySelector('#feedNewPost');
+ expect(newPostInput).not.toBeNull();
+
+ const buttons = app.querySelector('.botones');
+ expect(buttons).not.toBeNull();
+ });
+});
+
+describe('Feed test newPost buttons', () => {
+ test('Content in buttons', () => {
+ // Preparación
+ const app = document.createElement('div');
+ // Ejecucion con los actores: Aquí cargamos el HTML en el contenedor
+ app.innerHTML = feed.loadHTML();
+ // Aserción: Comprobamos la existencia de elementos específicos
+ const isButtonPublish = app.querySelector('#publish');
+ expect(isButtonPublish).not.toBeNull();
+
+ const isButtonCancel = app.querySelector('#cancel');
+ expect(isButtonCancel).not.toBeNull();
+ });
+});
+
+/* describe('Feed test div feedScrollContent', () => {
+ test('Content of elements in div feedScrollContent', () => {
+ // Preparación
+ const app = document.createElement('div');
+ // Ejecucion con los actores: Aquí cargamos el HTML en el contenedor
+ app.innerHTML = feed.loadEvents();
+ // Aserción: Comprobamos la existencia de elementos específicos
+ });
+}); */
+
+describe('Test function newPost', () => {
+ it('newPost is a function', () => {
+ expect(typeof newPost).toBe('function');
+ });
+});
+
+describe('Test function subscribeToDataChanges', () => {
+ it('subscribeToDataChanges is a funcion', () => {
+ expect(typeof subscribeToDataChanges).toBe('function');
+ });
+});
+
+describe('Test function logoutSesion', () => {
+ it('logoutSesion is a funcion', () => {
+ expect(typeof logoutSesion).toBe('function');
+ });
+});
+
+describe('Test function deletePost', () => {
+ it('deletePost is a funcion', () => {
+ expect(typeof deletePost).toBe('function');
+ });
+});
+
+describe('Test function updatePost', () => {
+ it('updatePost is a funcion', () => {
+ expect(typeof updatePost).toBe('function');
+ });
+});
+
+describe('Test function updatePostLike', () => {
+ it('updatePostLike is a funcion', () => {
+ expect(typeof updatePostLike).toBe('function');
+ });
+});
+
+describe('Test function getDataUser', () => {
+ it('getDataUser is a funcion', () => {
+ expect(typeof getDataUser).toBe('function');
+ });
+});
diff --git a/test/index.spec.js b/test/index.spec.js
deleted file mode 100644
index 91f11a3..0000000
--- a/test/index.spec.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// importamos la funcion que vamos a testear
-import { myFunction } from '../src/lib/index';
-
-describe('myFunction', () => {
- it('debería ser una función', () => {
- expect(typeof myFunction).toBe('function');
- });
-});
diff --git a/test/login.spec.js b/test/login.spec.js
new file mode 100644
index 0000000..d7dec56
--- /dev/null
+++ b/test/login.spec.js
@@ -0,0 +1,47 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import { loginWithGoogle, createUser, getUserByEmail } from '../src/components/login/login.controller';
+import login from '../src/components/login/login';
+
+describe('Test function loginWithGoogle', () => {
+ it('loginWithGoogle is a function', () => {
+ expect(typeof loginWithGoogle).toBe('function');
+ });
+});
+
+describe('Test function createUser', () => {
+ it('createUser is a function', () => {
+ expect(typeof createUser).toBe('function');
+ });
+});
+
+describe('Test function getUserByEmail ', () => {
+ it('getUserByEmail is a function', () => {
+ expect(typeof getUserByEmail).toBe('function');
+ });
+});
+
+describe('Button Login google test suite', () => {
+ test('Content a button in the interface', () => {
+ // preparacion
+ const app = document.createElement('div');
+ // ejecucion Los actores
+ app.innerHTML = login.loadHTML();
+ const isButton = app.querySelector('#btnLoginGoogle');
+ // asercion
+ expect(isButton).not.toBeNull();
+ });
+});
+describe(' formLogin test suite ', () => {
+ test('Content a button in the interface', () => {
+ // preparacion
+ const app = document.createElement('div');
+ // ejecucion Los actores
+ app.innerHTML = login.loadHTML();
+ const isButton = app.querySelector('#formLogin');
+ // asercion
+ expect(isButton).not.toBeNull();
+ });
+});
diff --git a/test/register.spec.js b/test/register.spec.js
new file mode 100644
index 0000000..15e22df
--- /dev/null
+++ b/test/register.spec.js
@@ -0,0 +1,17 @@
+/**
+ * @jest-environment jsdom
+ */
+
+import register from '../src/components/register/register';
+
+describe('Register test suite', () => {
+ test('Content a button in the interface', () => {
+ // preparacion
+ const app = document.createElement('div');
+ // ejecucion Los actores
+ app.innerHTML = register.loadHTML();
+ const isButton = app.querySelector('#Crearcuenta');
+ // asercion
+ expect(isButton).not.toBeNull();
+ });
+});