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: () => `
+
+
+ +
+ move_item +
+
+ +
+
+

Y si adoptas un nuevo mejor amigo? Por fis...

+
Abejita
+
Perrito
+
+
+

Crear nueva publicación

+ +
+ + +
+
+
+
+
`, + + 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: () => ` +
+
+ + +
+

Bienvenidos a:

+ +

Somos un espacio en donde podras consultar o publicar información acerca de + nuestros amigos de 4 patitas +

+
+
+
`, + + 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 +

+
+ +
+

Crear cuenta

+ + + + + + +
+ + + + + +

¿Ya tienes una cuenta registrada? + Ingresa aquí +

+ +

O ingresa con tu cuenta de Google

+
+ + + +
+
+ +
+
`, + 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(); + }); +});