diff --git a/src/Home/AuthPage/AuthPage.js b/src/Home/AuthPage/AuthPage.js index d845a99..a269c2c 100644 --- a/src/Home/AuthPage/AuthPage.js +++ b/src/Home/AuthPage/AuthPage.js @@ -22,7 +22,7 @@ class AuthPage extends Shadow { }) } - selectedPage = 2 // 1 == login, 2 == signup + selectedPage = 1 // 1 == login, 2 == signup render() { VStack(() => { @@ -60,7 +60,7 @@ class AuthPage extends Shadow { .color("var(--text)") .horizontalAlign("center") .margin("auto") - .marginTop(1, em) + .marginTop(7.5, em) .marginBottom(0, em) .gap(0.5, em) diff --git a/src/Home/AuthPage/Signup.js b/src/Home/AuthPage/Signup.js index e79a9d9..f34829c 100644 --- a/src/Home/AuthPage/Signup.js +++ b/src/Home/AuthPage/Signup.js @@ -25,12 +25,6 @@ class Signup extends Shadow { render() { form(() => { VStack(() => { - input("Email", "70vw") - .attr({ name: "email", type: "email" }) - .margin("auto") - .marginVertical(1, em) - .padding(1, em) - .styles(this.inputStyles) input("First Name", "70vw") .attr({ name: "firstName", type: "text" }) .margin("auto") @@ -43,6 +37,12 @@ class Signup extends Shadow { .marginVertical(1, em) .padding(1, em) .styles(this.inputStyles) + input("Email", "70vw") + .attr({ name: "email", type: "email" }) + .margin("auto") + .marginVertical(1, em) + .padding(1, em) + .styles(this.inputStyles) input("Password", "70vw") .attr({ name: "password", type: "password" }) .margin("auto") diff --git a/src/Profile/Profile.js b/src/Profile/Profile.js new file mode 100644 index 0000000..89d7a43 --- /dev/null +++ b/src/Profile/Profile.js @@ -0,0 +1,120 @@ +import server from "../_/code/bridge/serverFunctions"; + +css(` + profile- textarea::-webkit-scrollbar { + display: none; + width: 0px; + height: 0px; + } + + profile- textarea::-webkit-scrollbar-thumb { + background: transparent; + } + + profile- textarea::-webkit-scrollbar-track { + background: transparent; + } +`) + +class Profile extends Shadow { + constructor() { + super() + this.profile = global.profile + this.bioText = global.profile.bio ?? "" + } + + render() { + ZStack(() => { + p("X") + .color("var(--quillred") + .fontSize(4, em) + .position("absolute") + .top(0.5, rem) + .right(2, rem) + .zIndex(1001) + .onClick(() => { + $("appwindowcontainer-").closeProfile() + }) + + form(() => { + VStack(() => { + HStack(() => { }) // Profile Image placeholder + .boxSizing("border-box") + .height(10, em) + .width(10, em) + .paddingHorizontal(0.5, em) + .border("1px solid var(--accent)") + .borderRadius(100, pct) + .background("var(--darkaccent)") + + h1(this.profile.first_name + " " + this.profile.last_name) + .color("var(--headertext") + .width(70, pct) + .textAlign("center") + + h2("Bio") + .color("var(--headertext") + .margin(0) + .paddingVertical(0.9, em) + .borderTop("2px solid var(--divider)") + .width(70, pct) + .textAlign("center") + + textarea(this.bioText ? this.bioText : "Tap to start typing...") + .attr({ name: "bioinput" }) + .padding(1, em) + .width(90, pct) + .height(15, em) + .boxSizing("border-box") + .background("var(--searchbackground)") + .color("var(--darktext)") + .border("1px solid color-mix(in srgb, var(--accent) 60%, transparent)") + .borderRadius(12, px) + .fontFamily("Arial") + .fontSize(1.1, em) + .outline("none") + .onAppear((e) => { + if (this.bioText) { + $("profile- textarea").innerText = this.bioText + } + }) + .lineHeight(1.2, em) + + button("Save Bio") + .padding(1, em) + .fontSize(1.1, em) + .borderRadius(12, px) + .background("var(--searchbackground)") + .color("var(--text)") + .border("1px solid var(--accent)") + .boxSizing("border-box") + .marginVertical(0.75, em) + }) + .horizontalAlign("center") + .marginTop(5, em) + }) + .onSubmit(async (e) => { + e.preventDefault(); + const newBio = new FormData(e.target).get("bioinput"); + if (newBio.trim() !== this.profile.bio.trim()) { + const result = await server.editBio(newBio, this.profile.id) + const { bio, updated_at } = result.data + global.profile.bio = bio + global.profile.updated_at = updated_at + this.profile = global.profile + } + }) + }) + .backgroundColor("var(--main)") + .overflowX("hidden") + .height(window.visualViewport.height - 20, px) + .boxSizing("border-box") + .width(100, pct) + .position("fixed") + .top(20, px) + .zIndex(1000) + // }) + } +} + +register(Profile) \ No newline at end of file diff --git a/src/_/code/bridge/handlers.js b/src/_/code/bridge/handlers.js index ec31ebd..f0b4410 100644 --- a/src/_/code/bridge/handlers.js +++ b/src/_/code/bridge/handlers.js @@ -42,6 +42,10 @@ const handlers = { async getJobs(networkId) { return global.db.jobs.getByNetwork(networkId) }, + + async editBio(newBio, userId) { + return global.db.members.editBio(newBio, userId) + } } export default handlers \ No newline at end of file diff --git a/src/components/AppWindowContainer.js b/src/components/AppWindowContainer.js index 5d6e9c4..9a7e533 100644 --- a/src/components/AppWindowContainer.js +++ b/src/components/AppWindowContainer.js @@ -1,6 +1,9 @@ import "./AppWindow.js" +import "../Profile/Profile.js" class AppWindowContainer extends Shadow { + isProfileOpen = false + render() { ZStack(() => { @@ -11,12 +14,26 @@ class AppWindowContainer extends Shadow { }) .width(100, pct) .gap(0) + + if (this.isProfileOpen) { + Profile() + } }) .height(100, pct) .overflowY("hidden") .display("flex") .position("relative") } + + openProfile() { + this.isProfileOpen = true + this.rerender() + } + + closeProfile() { + this.isProfileOpen = false + this.rerender() + } } register(AppWindowContainer) \ No newline at end of file diff --git a/src/components/Sidebar.js b/src/components/Sidebar.js index e1952ea..87ff8f2 100644 --- a/src/components/Sidebar.js +++ b/src/components/Sidebar.js @@ -1,3 +1,5 @@ +import util from "../util" + class Sidebar extends Shadow { SidebarItem(text) { @@ -7,10 +9,18 @@ class Sidebar extends Shadow { .fontFamily("Sedan SC") .marginLeft(2, em) .fontStyle("italic") - .onClick(function () { + .onClick(function () { // BUG -- Fires twice every time if(this.innerText === "Home") { window.navigateTo("/") return + } else if (this.innerText === "Logout") { + $("sidebar-").close() + global.onLogout() + return + } else if (this.innerText === "Profile") { + $("appwindowcontainer-").openProfile() + $("sidebar-").close() + return } window.navigateTo(this.innerText.toLowerCase().replace(/\s+/g, "")) }) @@ -18,6 +28,7 @@ class Sidebar extends Shadow { render() { VStack(() => { + this.SidebarItem("Profile") this.SidebarItem("Home") this.SidebarItem("Map") this.SidebarItem("Logout") @@ -35,6 +46,12 @@ class Sidebar extends Shadow { .zIndex(3) } + close() { + if(this.style.right !== "-71vw") { + this.style.right = "-71vw" + } + } + toggle() { if(this.style.right === "-71vw") { this.style.right = "0vw" diff --git a/src/index.js b/src/index.js index 9cf2834..1053904 100644 --- a/src/index.js +++ b/src/index.js @@ -150,6 +150,16 @@ let Global = class { // navigateTo("/") } + async onLogout() { + await util.removeAuthToken() + await fetch(`${util.HOST}/signout`, { + method: "GET", + credentials: "include" + }); + this.profile = null + AuthPage() + } + constructor() { window.addEventListener("navigate", this.onNavigate) diff --git a/src/util.js b/src/util.js index fcf36e0..1dea37b 100644 --- a/src/util.js +++ b/src/util.js @@ -18,6 +18,10 @@ export default class util { }); } + static async removeAuthToken() { + await Preferences.remove({ key: 'auth_token'}) + } + static cssVariable(value) { return getComputedStyle(document.documentElement) .getPropertyValue("--" + value) diff --git a/vite.config.ts b/vite.config.ts index 74905fb..73993c2 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -24,6 +24,10 @@ export default defineConfig({ target: "http://localhost:10002", changeOrigin: true }, + "/signout": { + target: "http://localhost:10002", + changeOrigin: true + }, "/profile": { target: "http://localhost:10002", changeOrigin: true