diff --git a/src/Home/AuthPage/AuthPage.js b/src/Home/AuthPage/AuthPage.js index 44a9591..53da3f2 100644 --- a/src/Home/AuthPage/AuthPage.js +++ b/src/Home/AuthPage/AuthPage.js @@ -22,8 +22,6 @@ class AuthPage extends Shadow { }) } - selectedPage = 1 // 1 == login, 2 == signup - render() { VStack(() => { img(window.matchMedia('(prefers-color-scheme: dark)').matches ? "/_/icons/columnwhite.svg" : "/_/icons/logo.svg", window.isMobile() ? "5vmax" : "3vmax") @@ -35,24 +33,36 @@ class AuthPage extends Shadow { HStack(() => { p("Login") - .fontWeight(this.selectedPage === 1 ? "bold" : "normal") - .padding(0.75, em) - .borderRadius(12, px) - .background(this.selectedPage === 1 ? "var(--loginButton)" : "transparent") - .onTap(() => { - this.selectedPage = 1; - this.rerender(); - }) + .state(this, "selected", function (selected) { + if(selected === "1") { + this.fontWeight("bold") + this.background("var(--loginButton)") + } else { + this.fontWeight("normal") + this.background("transparent") + } + }) + .padding(0.75, em) + .borderRadius(12, px) + .onTap(() => { + this.attr("selected", "1") + }) p("Sign Up") - .fontWeight(this.selectedPage === 2 ? "bold" : "normal") - .padding(0.75, em) - .borderRadius(12, px) - .background(this.selectedPage === 2 ? "var(--loginButton)" : "transparent") - .onTap(() => { - this.selectedPage = 2; - this.rerender(); - }) + .state(this, "selected", function (selected) { + if(selected === "2") { + this.fontWeight("bold") + this.background("var(--loginButton)") + } else { + this.fontWeight("normal") + this.background("transparent") + } + }) + .padding(0.75, em) + .borderRadius(12, px) + .onTap(() => { + this.attr("selected", "2") + }) }) .fontFamily("Arial") .padding(0.25, em) @@ -65,16 +75,31 @@ class AuthPage extends Shadow { .marginBottom(2, em) .gap(0.5, em) - switch (this.selectedPage) { - case 1: - Login() - break; - case 2: - Signup() - break; - } + ZStack(() => { + + Login() + .state(this, "selected", function (selected) { + if(selected === "1") { + this.display("") + } else { + this.display("none") + } + }) + + Signup() + .state(this, "selected", function (selected) { + if(selected === "2") { + this.display("") + } else { + this.display("none") + } + }) + + }) + .attr("id", "content") }) + .attr("selected", "1") .width(100, vw) .height(100, vh) .margin(0) diff --git a/src/Home/AuthPage/Signup.js b/src/Home/AuthPage/Signup.js index f9fb3a6..f556082 100644 --- a/src/Home/AuthPage/Signup.js +++ b/src/Home/AuthPage/Signup.js @@ -20,8 +20,6 @@ class Signup extends Shadow { }) } - errorMessage = "" - render() { form(() => { VStack(() => { @@ -55,6 +53,24 @@ class Signup extends Shadow { .marginVertical(1, em) .padding(1, em) .styles(this.inputStyles) + p("") + .state("errormessage", function (msg) { + if(msg) { + this.display("") + this.innerText = msg + } else { + this.display("none") + this.innerText = "" + } + }) + .margin("auto") + .marginTop(1, em) + .color("var(--text)") + .fontFamily("Arial") + .opacity(.7) + .padding(0.5, em) + .backgroundColor("var(--darkred)") + .display("none") HStack(() => { button("==>") .padding(1, em) @@ -64,6 +80,13 @@ class Signup extends Shadow { .color("var(--text)") .border("1px solid var(--accent)") .boxSizing("border-box") + .onTouch(function (start) { + if (start) { + this.style.backgroundColor = "var(--accent)" + } else { + this.style.backgroundColor = "var(--searchbackground)" + } + }) }) .width(70, vw) .margin("auto") @@ -71,6 +94,7 @@ class Signup extends Shadow { .paddingLeft(0, em) .paddingRight(2, em) .marginVertical(1, em) + .marginBottom(10, em) .border("1px solid transparent") }) }) @@ -105,8 +129,7 @@ class Signup extends Shadow { global.renderHome(); } else { const { error } = await res.json(); - this.errorMessage = error; - console.error(this.errorMessage) + console.error(error) } } @@ -118,60 +141,62 @@ class Signup extends Shadow { const confirmPassword = data.get("confirmPassword"); if (!firstName || firstName.trim() === "") { - this.errorMessage = "First name is required."; + this.$("p").attr("errormessage", "First name is required.") return false } else if (firstName.trim().length < 2) { - this.errorMessage = "First name must be at least 2 characters."; + this.$("p").attr("errormessage", "First name must be at least 2 characters.") return false } else if (!/^[a-zA-Z\s'-]+$/.test(firstName.trim())) { - this.errorMessage = "First name contains invalid characters."; + this.$("p").attr("errormessage", "First name contains invalid characters.") return false } if (!lastName || lastName.trim() === "") { - this.errorMessage = "Last name is required."; + this.$("p").attr("errormessage", "Last name is required.") return false } else if (lastName.trim().length < 2) { - this.errorMessage = "Last name must be at least 2 characters."; + this.$("p").attr("errormessage", "Last name must be at least 2 characters.") return false } else if (!/^[a-zA-Z\s'-]+$/.test(lastName.trim())) { - this.errorMessage = "Last name contains invalid characters."; + this.$("p").attr("errormessage", "Last name contains invalid characters.") return false } if (!email || email.trim() === "") { - this.errorMessage = "Email is required."; + this.$("p").attr("errormessage", "Email is required.") return false } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim())) { - this.errorMessage = "Please enter a valid email address."; + this.$("p").attr("errormessage", "Please enter a valid email address.") return false } + let passwordError = `Password must be at least 7 characters and include an uppercase letter, a lowercase letter, a number, and a special character (!@#$%^&*(),.?":{}|<>)` + if (!password) { - this.errorMessage = "Password is required."; + this.$("p").attr("errormessage", "Password is required.") return false - } else if (password.length < 8) { - this.errorMessage = "Password must be at least 8 characters."; + } else if (password.length < 7) { + this.$("p").attr("errormessage", passwordError) return false } else if (!/[A-Z]/.test(password)) { - this.errorMessage = "Password must contain at least one uppercase letter."; + this.$("p").attr("errormessage", passwordError) return false } else if (!/[a-z]/.test(password)) { - this.errorMessage = "Password must contain at least one lowercase letter."; + this.$("p").attr("errormessage", passwordError) return false } else if (!/[0-9]/.test(password)) { - this.errorMessage = "Password must contain at least one number."; + this.$("p").attr("errormessage", passwordError) return false } else if (!/[!@#$%^&*(),.?":{}|<>]/.test(password)) { - this.errorMessage = "Password must contain at least one special character."; + this.$("p").attr("errormessage", passwordError) return false } if (!confirmPassword) { - this.errorMessage = "Please confirm your password."; + this.$("p").attr("errormessage", "Please confirm your password.") return false } else if (confirmPassword !== password) { - this.errorMessage = "Passwords do not match."; + this.$("p").attr("errormessage", "Passwords do not match.") return false } diff --git a/src/public/_/code/quill.js b/src/public/_/code/quill.js index f9622b6..24f5197 100644 --- a/src/public/_/code/quill.js +++ b/src/public/_/code/quill.js @@ -1,6 +1,7 @@ /* Sam Russell Captured Sun + 2.24.26 - Allowing state() to watch other elements 2.21.26 - Making state() be called on initial definition, fixing fontSize so it works with clamp(), other strings 2.20.26 - Adding state() 2.19.26 - Adding dynamicText() @@ -700,19 +701,34 @@ HTMLElement.prototype.horizontalAlign = function (value) { /* Elements */ -HTMLElement.prototype.state = function(attr, cb) { +HTMLElement.prototype.state = function(arg1, arg2, arg3) { + let el; + let attr; + let cb; + + if(arg3) { + el = arg1 + attr = arg2 + cb = arg3 + } else { + el = this + attr = arg1 + cb = arg2 + } + if (attr !== attr.toLowerCase()) { throw new Error(`quill: dynamicText() attr "${attr}" must be lowercase`); } - new MutationObserver(() => { - const value = this.getAttribute(attr); + let handler = () => { + const value = el.getAttribute(attr); cb.call(this, value) - }) - .observe(this, { attributes: true, attributeFilter: [attr] }); + } - const value = this.getAttribute(attr); - cb.call(this, value) + new MutationObserver(handler) + .observe(el, { attributes: true, attributeFilter: [attr] }); + + handler() return this } @@ -1230,22 +1246,23 @@ HTMLElement.prototype.removeAllListeners = function() { /* ATTRIBUTES */ -HTMLElement.prototype.attr = function(attributes) { - if ( - typeof attributes !== "object" || - attributes === null || - Array.isArray(attributes) - ) { - throw new TypeError("attr() expects an object with key-value pairs"); - } - - for (const [key, value] of Object.entries(attributes)) { - if(value === null) { - this.removeAttribute(key) - } else { - this.setAttribute(key, value); +HTMLElement.prototype.attr = function(arg1, arg2) { + if(typeof arg1 === "object") { + for (const [key, value] of Object.entries(arg1)) { + if(value === null) { + this.removeAttribute(key) + } else { + this.setAttribute(key, value); + } } - } - return this; + return this; + } else if(typeof arg1 === "string" && arg2) { + this.setAttribute(arg1, arg2) + return this + } else if(typeof arg1 === "string") { + return this.getAttribute("") + } else { + throw new TypeError("wrong parameter for attr(): ", arg1); + } };