diff --git a/staff/daniel-guillen/socialcode/app/components/Component.js b/staff/daniel-guillen/socialcode/app/components/Component.js new file mode 100644 index 000000000..3da1c66e3 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/Component.js @@ -0,0 +1,60 @@ +class Component { + constructor(tagNameOrContainer = 'div') { + if (typeof tagNameOrContainer === 'string') + this.container = document.createElement(tagNameOrContainer) + else if (tagNameOrContainer instanceof HTMLElement || tagNameOrContainer instanceof HTMLDocument) + this.container = tagNameOrContainer + else + throw new Error('tagNameOrContainer is not a tagName or container') + + this.children = [] + } + + add(child) { + if (!(child instanceof Component)) throw new TypeError('child is not component') + + this.children.push(child) + + this.container.appendChild(child.container) + } + + remove(child) { + if (!(child instanceof Component)) throw new TypeError('child is not component') + + const index = this.children.indexOf(child) + + if (index > -1) + this.children.splice(index, 1) + + if (this.container.contains(child.container)) + this.container.removeChild(child.container) + } + + setText(text) { + this.container.innerText = text + } + + setId(id) { + this.container.id = id + } + + addClass(clazz) { + this.container.classList.add(clazz) + } + + removeClass(clazz) { + this.container.classList.remove(clazz) + } + + onClick(listener) { + this.container.addEventListener('click', listener) + } + + onKeyDown(listener) { + this.container.addEventListener('keydown', listener) + } + + onKeyUp(listener) { + this.container.addEventListener('keyup', listener) + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/Post.js b/staff/daniel-guillen/socialcode/app/components/Post.js new file mode 100644 index 000000000..2abd1b0d6 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/Post.js @@ -0,0 +1,22 @@ +class Post extends Component { + constructor(post) { + super('article') + + const authorTitle = new Component('p') + authorTitle.setText(post.author) + + const postTitle = new Component('h2') + postTitle.setText(post.title) + + const postImage = new Image + postImage.setUrl(post.image) + + const postText = new Component('p') + postText.setText(post.text) + + this.add(authorTitle) + this.add(postTitle) + this.add(postImage) + this.add(postText) + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Button.css b/staff/daniel-guillen/socialcode/app/components/core/Button.css new file mode 100644 index 000000000..d45aa1b0b --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Button.css @@ -0,0 +1,6 @@ +.Button { + padding: .4rem; + background-color: transparent; + font-size: 1rem; + border: 1px solid var(--first-color); +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Button.js b/staff/daniel-guillen/socialcode/app/components/core/Button.js new file mode 100644 index 000000000..6acbefc57 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Button.js @@ -0,0 +1,11 @@ +class Button extends Component { + constructor() { + super('button') + + this.addClass('Button') + } + + setType(type) { + this.container.type = type + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Field.css b/staff/daniel-guillen/socialcode/app/components/core/Field.css new file mode 100644 index 000000000..708f5849b --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Field.css @@ -0,0 +1,5 @@ +.Field { + display: flex; + flex-direction: column; + margin: .25rem 0; +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Field.js b/staff/daniel-guillen/socialcode/app/components/core/Field.js new file mode 100644 index 000000000..201360e2f --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Field.js @@ -0,0 +1,28 @@ +class Field extends Component { + constructor(id, type, text) { + super('div') + + this.addClass('Field') + + const label = new Label + label.setText(text) + label.setFor(id) + + const input = new Input + input.setId(id) + input.setType(type) + + this.add(label) + this.add(input) + } + + setPlaceholder(placeholder) { + this.children[1].setPlaceholder(placeholder) + } + + getValue() { + const input = this.children[1] + + return input.getValue() + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Form.css b/staff/daniel-guillen/socialcode/app/components/core/Form.css new file mode 100644 index 000000000..379cad316 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Form.css @@ -0,0 +1,5 @@ +.Form { + display: flex; + flex-direction: column; + align-items: center; +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Form.js b/staff/daniel-guillen/socialcode/app/components/core/Form.js new file mode 100644 index 000000000..62377cef5 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Form.js @@ -0,0 +1,15 @@ +class Form extends Component { + constructor() { + super('form') + + this.addClass('Form') + } + + onSubmit(listener) { + this.container.addEventListener('submit', listener) + } + + clear() { + this.container.reset() + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Heading.js b/staff/daniel-guillen/socialcode/app/components/core/Heading.js new file mode 100644 index 000000000..093dde937 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Heading.js @@ -0,0 +1,5 @@ +class Heading extends Component { + constructor(level) { + super('h' + level) + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Image.css b/staff/daniel-guillen/socialcode/app/components/core/Image.css new file mode 100644 index 000000000..d1abcb0ea --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Image.css @@ -0,0 +1,3 @@ +.Image { + width: 100%; +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Image.js b/staff/daniel-guillen/socialcode/app/components/core/Image.js new file mode 100644 index 000000000..70988c875 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Image.js @@ -0,0 +1,15 @@ +class Image extends Component { + constructor() { + super('img') + + this.addClass('Image') + } + + setUrl(url) { + this.container.src = url + } + + setAltText(altText) { + this.container.alt = altText + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Input.css b/staff/daniel-guillen/socialcode/app/components/core/Input.css new file mode 100644 index 000000000..6c09b66f6 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Input.css @@ -0,0 +1,6 @@ +.Input { + padding: .4rem; + background-color: transparent; + font-size: 1rem; + border: 1px solid var(--first-color); +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Input.js b/staff/daniel-guillen/socialcode/app/components/core/Input.js new file mode 100644 index 000000000..9b6509cd7 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Input.js @@ -0,0 +1,19 @@ +class Input extends Component { + constructor() { + super('input') + + this.addClass('Input') + } + + setType(type) { + this.container.type = type + } + + setPlaceholder(placeholder) { + this.container.placeholder = placeholder + } + + getValue() { + return this.container.value + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Label.js b/staff/daniel-guillen/socialcode/app/components/core/Label.js new file mode 100644 index 000000000..4bbf3b03e --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Label.js @@ -0,0 +1,9 @@ +class Label extends Component { + constructor() { + super('label') + } + + setFor(id) { + this.container.htmlFor = id + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/Link.js b/staff/daniel-guillen/socialcode/app/components/core/Link.js new file mode 100644 index 000000000..7f074dce8 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/Link.js @@ -0,0 +1,15 @@ +class Link extends Component { + constructor() { + super('a') + + this.setUrl('') + } + + setUrl(url) { + this.container.href = url + } + + setTarget(target) { + this.container.target = target + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/SubmitButton.css b/staff/daniel-guillen/socialcode/app/components/core/SubmitButton.css new file mode 100644 index 000000000..4452ec3b8 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/SubmitButton.css @@ -0,0 +1,3 @@ +.SubmitButton { + margin: .5rem 0; +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/core/SubmitForm.js b/staff/daniel-guillen/socialcode/app/components/core/SubmitForm.js new file mode 100644 index 000000000..6cfc25781 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/core/SubmitForm.js @@ -0,0 +1,10 @@ +class SubmitButton extends Button { + constructor(text) { + super() + + this.addClass('SubmitButton') + + this.setType('submit') + this.setText(text) + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/library/FormWithFeedback.css b/staff/daniel-guillen/socialcode/app/components/library/FormWithFeedback.css new file mode 100644 index 000000000..0e7015959 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/library/FormWithFeedback.css @@ -0,0 +1,11 @@ +.FormWithFeedback { + padding: 1rem; +} + +.FormWithFeedback .Feedback { + color: tomato; +} + +.FormWithFeedback .Feedback.success { + color: greenyellow; +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/components/library/FormWithFeedback.js b/staff/daniel-guillen/socialcode/app/components/library/FormWithFeedback.js new file mode 100644 index 000000000..f36bb7f88 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/components/library/FormWithFeedback.js @@ -0,0 +1,30 @@ +class FormWithFeedback extends Form { + constructor() { + super() + + this.addClass('FormWithFeedback') + + const feedbackPanel = new Component('p') + feedbackPanel.addClass('Feedback') + + this.feedbackPanel = feedbackPanel + } + + setFeedback(message, level) { + if (level === 'success') + this.feedbackPanel.addClass('success') + + this.feedbackPanel.setText(message) + + this.add(this.feedbackPanel) + } + + clear() { + super.clear() + + this.feedbackPanel.setText('') + this.feedbackPanel.removeClass('success') + + this.remove(this.feedbackPanel) + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/data.js b/staff/daniel-guillen/socialcode/app/data.js new file mode 100644 index 000000000..194c90029 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/data.js @@ -0,0 +1,53 @@ +const data = {} + +data.findUser = callback => { + const usersJson = localStorage.users + + if (!usersJson) usersJson = '[]' + + const users = JSON.parse(usersJson) + + const user = users.find(callback) + + return user +} + +data.insertUser = user => { + let usersJson = localStorage.users + + if (!usersJson) usersJson = '[]' + + const users = JSON.parse(usersJson) + + users.push(user) + + usersJson = JSON.stringify(users) + + localStorage.users = usersJson +} + +data.findPosts = callback => { + const postsJson = localStorage.posts + + if (!postsJson) postsJson = '[]' + + const posts = JSON.parse(postsJson) + + const filtered = posts.filter(callback) + + return filtered +} + +data.insertPost = post => { + let postsJson = localStorage.posts + + if (!postsJson) postsJson = '[]' + + const posts = JSON.parse(postsJson) + + posts.push(post) + + postsJson = JSON.stringify(posts) + + localStorage.posts = postsJson +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/errors.js b/staff/daniel-guillen/socialcode/app/errors.js new file mode 100644 index 000000000..432cf244c --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/errors.js @@ -0,0 +1,28 @@ +/* La clase `...Error` extiende la clase `Error` en JavaScript y establece su propia propiedad de nombre en +el nombre del constructor. */ + +class ContentError extends Error { + constructor(message) { + super(message) + + //this.name = ContentError.name + this.name = this.constructor.name + } +} + + +class MatchError extends Error { + constructor(message) { + super(message) + + this.name = this.constructor.name + } +} + +class DuplicityError extends Error { + constructor(message) { + super(message) + + this.name = this.constructor.name + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/global.css b/staff/daniel-guillen/socialcode/app/global.css new file mode 100644 index 000000000..2743e592f --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/global.css @@ -0,0 +1,17 @@ + +@import url('https://fonts.googleapis.com/css2?family=Pixelify+Sans:wght@400..700&display=swap'); + +:root { + --first-color: white; + --second-color: rgb(28, 27, 27); +} + +* { + font-family: "Pixelify Sans"; + color: var(--first-color); +} + +body { + background-color: var(--second-color); + margin: 0; +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/home/components/CreatePostForm.js b/staff/daniel-guillen/socialcode/app/home/components/CreatePostForm.js new file mode 100644 index 000000000..ff8016c75 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/home/components/CreatePostForm.js @@ -0,0 +1,41 @@ +class CreatePostForm extends FormWithFeedback { + constructor() { + super() + + this.addClass('CreatePostForm') + + const titleField = new Field('title', 'text', 'Title') + titleField.setPlaceholder('title') + + const imageField = new Field('image', 'text', 'Image') + imageField.setPlaceholder('image') + + const descriptionField = new Field('description', 'text', 'Description') + descriptionField.setPlaceholder('description') + + const submitButton = new SubmitButton('Create') + + this.add(titleField) + this.add(imageField) + this.add(descriptionField) + this.add(submitButton) + } + + getTitle() { + const titleField = this.children[0] + + return titleField.getValue() + } + + getImage() { + const imageField = this.children[1] + + return imageField.getValue() + } + + getDescription() { + const descriptionField = this.children[2] + + return descriptionField.getValue() + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/home/components/Post.js b/staff/daniel-guillen/socialcode/app/home/components/Post.js new file mode 100644 index 000000000..203d9a8e2 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/home/components/Post.js @@ -0,0 +1,26 @@ +class Post extends Component { + constructor(post) { + super('article') + + const authorTitle = new Component('p') + authorTitle.setText(post.author) + + const postTitle = new Component('h2') + postTitle.setText(post.title) + + const postImage = new Image + postImage.setUrl(post.image) + + const postDescription = new Component('p') + postDescription.setText(post.description) + + const postDate = new Component('time') + postDate.setText(post.date) + + this.add(authorTitle) + this.add(postTitle) + this.add(postImage) + this.add(postDescription) + this.add(postDate) + } +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/home/index.css b/staff/daniel-guillen/socialcode/app/home/index.css new file mode 100644 index 000000000..94927e6d9 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/home/index.css @@ -0,0 +1,30 @@ +.View { + display: flex; + flex-direction: column; + align-items: center; + margin: 4rem 2rem; +} + +.Header { + display: flex; + gap: 1rem; + width: 100%; + justify-content: right; + position: fixed; + top: 0; + padding: .5rem; + box-sizing: border-box; + border-bottom: 1px solid var(--first-color); + background-color: var(--second-color); +} + +.Footer { + width: 100%; + display: flex; + justify-content: center; + position: fixed; + bottom: 0; + padding: .5rem 0; + border-top: 1px solid var(--first-color); + background-color: var(--second-color); +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/home/index.html b/staff/daniel-guillen/socialcode/app/home/index.html new file mode 100644 index 000000000..9e170e3e1 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/home/index.html @@ -0,0 +1,46 @@ + + + + + + + SOCIAL CODE - Welcome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/home/index.js b/staff/daniel-guillen/socialcode/app/home/index.js new file mode 100644 index 000000000..791889b9e --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/home/index.js @@ -0,0 +1,73 @@ +if (!logic.isUserLoggedIn()) + location.href = '../login' + +const view = new Component(document.body) +view.addClass('View') + +const header = new Component('header') +header.addClass('Header') +view.add(header) + +const userName = logic.getUserName() + +const usernameTitle = new Heading(3) +usernameTitle.setText(userName) +header.add(usernameTitle) + +const logoutButton = new Button +logoutButton.setText('Logout') + +logoutButton.onClick(() => { + logic.logoutUser() + + location.href = '../login' +}) + +header.add(logoutButton) + +const main = new Component('main') +view.add(main) + +const postList = new Component('section') +main.add(postList) + +const posts = logic.getAllPosts() + +posts.forEach(post => { + const post2 = new Post(post) + + postList.add(post2) +}) +const createPostForm = new CreatePostForm + +createPostForm.onSubmit(event => { + event.preventDefault() + + const title = createPostForm.getTitle() + const image = createPostForm.getImage() + const description = createPostForm.getDescription() + + try { + logic.createPost(title, image, description) + + // TODO dismount create post form from main + // TODO refresh post list + } catch (error) { + if (error instanceof ContentError) + createPostForm.setFeedback(error.message + ', please, correct it') + else + createPostForm.setFeedback('sorry, there was an error, please try again later') + } +}) + + +// TODO mount create post form when clicking on plus button +main.add(createPostForm) + +const footer = new Component('footer') +footer.addClass('Footer') +view.add(footer) + +const addPostButton = new Button +addPostButton.setText('+') +footer.add(addPostButton) diff --git a/staff/daniel-guillen/socialcode/app/logic.js b/staff/daniel-guillen/socialcode/app/logic.js new file mode 100644 index 000000000..5324c94a8 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/logic.js @@ -0,0 +1,120 @@ +const logic = {} + +/* Estas expresiones regulares se utilizan para la validación en el proceso de +registro de usuario en el formulario proporcionado. */ +const EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|.(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ +const USERNAME_REGEX = /^[\w-]+$/ +const PASSWORD_REGEX = /^[\w-$%&=\[\]\{\}\<\>\(\)]{4,}$/ + +const NAME_REGEX = /^[a-zA-Z=\[\]\{\}\<\>\(\)]{1,}$/ + +/* La función `logic.registerUser` es responsable de registrar un nuevo usuario en el sistema. +Se necesita completar correctamente campos como `nombre`, `apellido`, `correo electrónico`, +`nombre de usuario`, `contraseña` y `repetir contraseña`. +De lo contrario mandara un aviso o error mediante un Feedback dentro del Form */ +logic.registerUser = (name, surname, email, username, password, passwordRepeat) => { + if (!NAME_REGEX.test(name)) + throw new ContentError('Name is not valid ⛔') + + if (!NAME_REGEX.test(surname)) + throw new ContentError('Surname is not valid ⛔') + + if (!EMAIL_REGEX.test(email)) + throw new ContentError('Email is not valid ⛔') + + if (!USERNAME_REGEX.test(username)) + throw new ContentError('Username is not valid ⛔') + + if (!PASSWORD_REGEX.test(password)) + throw new ContentError('Password is not valid ⛔') + + if (password !== passwordRepeat) + throw new MatchError('Passwords don\'t match 😵') + + const user = data.findUser(user => user.email === email || user.username === username) + + if (user) + throw new DuplicityError('User already exists ⛔') + + user = { + name: name, + surname: surname, + email: email, + username: username, + password: password + } + + data.insertUser(user) +} + +/* La función `logic.loginUser` es responsable de manejar el proceso de inicio de sesión de un usuario. +Se necesita completar correctamente dos campos, "nombre de usuario" y "contraseña". Aquí hay un desglose de lo que hace: */ +logic.loginUser = (username, password) => { + if (!USERNAME_REGEX.test(username)) + throw new ContentError('username is not valid ⛔') + + if (!PASSWORD_REGEX.test(password)) + throw new ContentError('password is not valid ⛔') + + const user = data.findUser(user => user.username === username) + + if (!user) + throw new MatchError('user not found 🔎') + + if (user.password !== password) + throw new MatchError('wrong password 😵') + + sessionStorage.username = username +} + +/* `logic.isUserLoggedIn = () => !!sessionStorage.username` es una función que verifica si un usuario está +actualmente conectado. Devuelve "verdadero" si hay un valor almacenado en "sessionStorage.username", +indicando que un usuario ha iniciado sesión. +Los dobles signos de exclamación `!!` se utilizan para convertir el valor +a un booleano, asegurando que la función devuelva "verdadero" si el usuario ha iniciado sesión o "falso" +si el usuario no ha iniciado sesión. */ +logic.isUserLoggedIn = () => !!sessionStorage.username + +/* esta función es responsable de cerrar la sesión de un usuario. Cuando se llama a esta función, se elimina +la clave `username` del objeto `sessionStorage`, desconectando al usuario eliminando su información de sesión almacenada. +Esta acción borra los datos de la sesión del usuario, indicando que ya no están conectados. */ +logic.logoutUser = () => delete sessionStorage.username + +/* La función `logic.getUserName` recupera el nombre del usuario actualmente conectado. 1º encuentra el objeto de usuario +en el almacenamiento de datos cuyo nombre de usuario coincide con el nombre de usuario almacenado en el `sessionStorage`. +Luego, devuelve el nombre de ese usuario. Esta función es útil para mostrar el nombre del usuario que inició sesión +en la interfaz de usuario o en un lugar determinado de app. */ +logic.getUserName = () => { + const user = data.findUser(user => user.username === sessionStorage.username) + + return user.name +} + +/* La función `logic.getAllPosts` recupera todas las publicaciones del almacenamiento de datos. +Llama a la función `data.findPosts` con una función de devolución de llamada que siempre devuelve verdadero, recupera +todos los mensajes. Luego, invierte el orden de las publicaciones usando el método "inverso" antes de regresar a ellos. +Esto garantiza que las publicaciones se muestren en orden cronológico inverso, más recientes primero. */ +logic.getAllPosts = () => { + const posts = data.findPosts(() => true) + + return posts.reverse() +} + +/* La función `logic.createPost` es responsable de crear una nueva publicación en el sistema, es necesario tres +parámetros: `título`, `imagen` y `descripción`. */ + +logic.createPost = (title, image, description) => { + if (typeof title !== 'string' || !title.length || title.length > 50) throw new ContentError('title is not valid ⛔') + if (typeof image !== 'string' || !image.startsWith('http')) throw new ContentError('image is not valid ⛔') + if (typeof description !== 'string' || !description.length || description.length > 200) throw new ContentError('description is not valid ⛔') + + const post = { + author: sessionStorage.username, + title, + image, + description, + date: new Date().toISOString() + } + + data.insertPost(post) +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/login/LoginForm.js b/staff/daniel-guillen/socialcode/app/login/LoginForm.js new file mode 100644 index 000000000..c329d9149 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/login/LoginForm.js @@ -0,0 +1,58 @@ +class LoginForm extends FormWithFeedback { + constructor() { + super() + + this.addClass('LoginForm') + + const usernameField = new Field('username', 'text', 'Username') + usernameField.setPlaceholder('username') + + const passwordField = new Field('password', 'password', 'Password') + passwordField.setPlaceholder('password') + + const submitButton = new SubmitButton('Login') + + //const feedbackPanel = new Component('p') + //feedbackPanel.addClass('Feedback') + + //this.feedbackPanel = feedbackPanel + + this.add(usernameField) + this.add(passwordField) + this.add(submitButton) + //this.add(this.feedbackPanel) + } + + getUsername() { + const usernameField = this.children[0] + + return usernameField.getValue() + } + + getPassword() { + const passwordField = this.children[1] + + return passwordField.getValue() + } + /* setFeedback(message, level) { + //const feedbackPanel = this.children[this.children.length - 1] + + if (level === 'success') + feedbackPanel.addClass('success') + + this.feedbackPanel.setText(message) + + this.add(this.feedbackPanel) + } + + clear() { + super.clear() + + //const feedbackPanel = this.children[this.children.length - 1] + + this.feedbackPanel.setText('') + this.feedbackPanel.removeClass('success') + + this.remove(this.feedbackPanel) + } */ +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/login/index.css b/staff/daniel-guillen/socialcode/app/login/index.css new file mode 100644 index 000000000..968ff685b --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/login/index.css @@ -0,0 +1,5 @@ +.View { + display: flex; + flex-direction: column; + align-items: center; +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/login/index.html b/staff/daniel-guillen/socialcode/app/login/index.html new file mode 100644 index 000000000..c24516253 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/login/index.html @@ -0,0 +1,46 @@ + + + + + + + SOCIAL CODE - Login + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/login/index.js b/staff/daniel-guillen/socialcode/app/login/index.js new file mode 100644 index 000000000..d101146c3 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/login/index.js @@ -0,0 +1,53 @@ +if (logic.isUserLoggedIn()) + location.href = '../home' + +const view = new Component(document.body) +view.addClass('View') + +const title = new Heading(1) +title.setText('Welcome - Login') + +/* Cuando se envía el formulario, se recupera el nombre de usuario y la contraseña ingresados ​​en los campos del loginForm, +se inicia sesión con usuario utilizando la función `logic.loginUser` si las credenciales proporcionadas son correctas. +Si los datos introducidos en los campos no son validos se lanzan avisos o errores mediante Feedback dentro de Form */ +const loginForm = new LoginForm +loginForm.onSubmit(event => { + event.preventDefault() + + const username = loginForm.getUsername() + const password = loginForm.getPassword() + + try { + logic.loginUser(username, password) + + loginForm.clear() + + loginForm.setFeedback('User successfully logged in 🎉', 'success') + + setTimeout(() => location.href = '../home', 1000) + } catch (error) { + if (error instanceof ContentError){ + loginForm.setFeedback(error.message + ', please, correct it 👌') + } + else if (error instanceof MatchError){ + loginForm.setFeedback('wrong credentials 😵') + } + else{ + loginForm.setFeedback('😵 Sorry, there was an error, please try again later ⏳') + } + //setTimeout(() => loginForm.setFeedback(""), 4000,) + } +}) + + +const registerLink = new Link +registerLink.setText('Register') +registerLink.onClick(event => { + event.preventDefault() + + setTimeout(() => location.href = '../register', 500) +}) + +view.add(title) +view.add(loginForm) +view.add(registerLink) \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/register/RegisterForm.js b/staff/daniel-guillen/socialcode/app/register/RegisterForm.js new file mode 100644 index 000000000..033dcc803 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/register/RegisterForm.js @@ -0,0 +1,102 @@ +/* Este fragmento de código define una class llamada "RegisterForm" que extiende "FormWithFeedback". Adentro +el constructor de `RegisterForm`, inicializa varios campos del formulario como nombre, apellido, correo electrónico, +nombre de usuario, contraseña y repetir contraseña utilizando la class `Field`. A cada Field se le asigna un tipo, +etiqueta y valor de marcador de posición. Además, se crea un botón de envío utilizando `SubmitButton`. */ +class RegisterForm extends FormWithFeedback { + constructor() { + super() + + this.addClass('RegisterForm') + + const nameField = new Field('name', 'text', 'Name') + nameField.setPlaceholder('name') + + const surnameField = new Field('surname', 'text', 'Surname') + surnameField.setPlaceholder('surname') + + const emailField = new Field('email', 'email', 'E-mail') + emailField.setPlaceholder('name@example.com') + + const usernameField = new Field('username', 'text', 'Username') + usernameField.setPlaceholder('username') + + const passwordField = new Field('password', 'password', 'Password') + passwordField.setPlaceholder('password') + + const passwordRepeatField = new Field('repassword', 'password', 'Password repeat') + passwordRepeatField.setPlaceholder('repeat password') + + const submitButton = new SubmitButton('Register') + + //const feedbackPanel = new Component('p') + //feedbackPanel.addClass('Feedback') + + //this.feedbackPanel = feedbackPanel + + this.add(nameField) + this.add(surnameField) + this.add(emailField) + this.add(usernameField) + this.add(passwordField) + this.add(passwordRepeatField) + this.add(submitButton) + //this.add(feedbackPanel) + } + + getName() { + const nameField = this.children[0] + + return nameField.getValue() + } + + getSurname() { + const surnameField = this.children[1] + + return surnameField.getValue() + } + + getEmail() { + const emailField = this.children[2] + + return emailField.getValue() + } + + getUsername() { + const usernameField = this.children[3] + + return usernameField.getValue() + } + + getPassword() { + const passwordField = this.children[4] + + return passwordField.getValue() + } + + getPasswordRepeat() { + const passwordFieldRepeat = this.children[5] + + return passwordFieldRepeat.getValue() + } + /*setFeedback(message, level) { + //const feedbackPanel = this.children[this.children.length - 1] + + if (level === 'success') + feedbackPanel.addClass('success') + + this.feedbackPanel.setText(message) + + this.add(this.feedbackPanel) + } + + clear() { + super.clear() + + //const feedbackPanel = this.children[this.children.length - 1] + + this.feedbackPanel.setText('') + this.feedbackPanel.removeClass('success') + + this.remove(this.feedbackPanel) + } */ +} diff --git a/staff/daniel-guillen/socialcode/app/register/index.css b/staff/daniel-guillen/socialcode/app/register/index.css new file mode 100644 index 000000000..968ff685b --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/register/index.css @@ -0,0 +1,5 @@ +.View { + display: flex; + flex-direction: column; + align-items: center; +} \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/register/index.html b/staff/daniel-guillen/socialcode/app/register/index.html new file mode 100644 index 000000000..3568ca2c1 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/register/index.html @@ -0,0 +1,46 @@ + + + + + + + SOCIAL CODE - Register + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/staff/daniel-guillen/socialcode/app/register/index.js b/staff/daniel-guillen/socialcode/app/register/index.js new file mode 100644 index 000000000..4853ab873 --- /dev/null +++ b/staff/daniel-guillen/socialcode/app/register/index.js @@ -0,0 +1,64 @@ +/* Se comprueba si el usuario ya está conectado. Si el usuario ha iniciado sesión, lo redirigirá a la página de 'home'. +Esta es una práctica común en las aplicaciones web para redirigir automáticamente a los usuarios. +a una página específica si ya están logueados.*/ +if (logic.isUserLoggedIn()) + location.href = '../home' + +const view = new Component(document.body) +view.addClass('View') + +const title = new Heading(1) +title.setText('Welcome - Register') +title.onClick(() => alert('By clicking on this title you wont get anything 😒')) + +/* Aqui se maneja el envío de un formulario de registro. +Cuando se envía el formulario, evita el comportamiento de envío de formulario por defecto, +se recupera los valores de entrada de los campos del formulario (nombre, apellido, correo electrónico, nombre de usuario, contraseña, contraseñaRepeat) +para hacer el guardado con la funcion en logic 'registerUser' si son validos se redirige a 'login' +sino se recibira avisos o errores mediante Feedbacks dentro del Form */ +const registerForm = new RegisterForm +registerForm.onSubmit(event => { + event.preventDefault() + + const name = registerForm.getName() + const surname = registerForm.getSurname() + const email = registerForm.getEmail() + const username = registerForm.getUsername() + const password = registerForm.getPassword() + const passwordRepeat = registerForm.getPasswordRepeat() + + try { + logic.registerUser(name, surname, email, username, password, passwordRepeat) + + registerForm.clear() + + registerForm.setFeedback('user successfully registered 🎉', 'success') + + setTimeout(() => location.href = '../login', 1000) + } catch (error) { + if (error instanceof ContentError) { + registerForm.setFeedback(error.message + ', please, correct it 👌') + } + else if (error instanceof MatchError) { + registerForm.setFeedback(error.message + ', please, retype them 👌') + } + else if (error instanceof DuplicityError) { + registerForm.setFeedback(error.message + ', please, enter new one 👌') + } + else { + registerForm.setFeedback('😵 Sorry, there was an error, please try again later ⏳') + } + setTimeout(() => registerForm.setFeedback(""), 4000) +}}) + +const loginLink = new Link +loginLink.setText('Login') +loginLink.onClick(event => { + event.preventDefault() + + setTimeout(() => location.href = '../login', 500) +}) + +view.add(title) +view.add(registerForm) +view.add(loginLink) \ No newline at end of file