matrix-art

An image gallery for Matrix
git clone git://archive.git.mtrnord.blog/MTRNord/matrix-art.git
Log | Files | Refs | README | LICENSE

commit ce192aa025e8c3b280b0244a47c35a9b36eaf440
parent b87a45ae935227bc4b10ef6f886b4767369fa265
Author: MTRNord <mtrnord1@gmail.com>
Date:   Wed,  4 Jan 2023 00:17:13 +0100

Convert Join page to functional component

Diffstat:
Dsrc/components/hookHelpers.tsx | 10----------
Msrc/pages/Join.tsx | 146++++++++++++++++++++++++++++++++++++-------------------------------------------
2 files changed, 67 insertions(+), 89 deletions(-)

diff --git a/src/components/hookHelpers.tsx b/src/components/hookHelpers.tsx @@ -1,9 +0,0 @@ -import { useNavigate } from "react-router-dom"; - -export const withNavigateHOC = (Component: any) => { - return (props: any) => { - const navigate = useNavigate(); - - return <Component navigate={navigate} {...props} />; - }; -}; -\ No newline at end of file diff --git a/src/pages/Join.tsx b/src/pages/Join.tsx @@ -1,100 +1,88 @@ -import React, { PureComponent } from "react"; +import React, { useState, useContext } from "react"; import { Client } from "../context"; import { Header } from "../components/header"; -import { MatrixClient } from "../matrix/client"; -import { NavigateFunction } from "react-router-dom"; -import { withNavigateHOC } from "../components/hookHelpers"; - -type Props = { - navigate: NavigateFunction; -}; - -type State = { - homeserver: string; - username: string; - password: string; - create_profile: boolean; - current_tab: "login" | "register"; -}; +import { useNavigate } from "react-router-dom"; const ACTIVE_TAB_CSS = "inline-block p-4 w-full text-gray-900 bg-gray-100 hover:ring-blue-300 hover:ring-1 focus:ring-transparent focus:outline-none dark:bg-gray-700 dark:text-white"; const TAB_CSS = "inline-block p-4 w-full bg-white hover:text-gray-700 hover:bg-gray-50 hover:ring-blue-300 hover:ring-1 focus:ring-transparent focus:outline-none dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700"; -class Join extends PureComponent<Props, State> { - static contextType = Client; - declare context: React.ContextType<typeof Client>; +export default function Join() { + const navigate = useNavigate(); + const client = useContext(Client); + const [homeserver, setHomeserver] = useState(import.meta.env.VITE_MATRIX_SERVER_URL); + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + const [createProfile, setCreateProfile] = useState(true); + const [currentTab, setCurrentTab] = useState("login"); - constructor(props: Props) { - super(props); - this.state = { - homeserver: "https://art.midnightthoughts.space", - username: "", - password: "", - create_profile: true, - current_tab: "login" - }; - } - - async onSubmit(e: React.FormEvent) { - const client: MatrixClient | undefined = this.context; + const onSubmit = async (e: React.FormEvent) => { if (!client) { return; } - if (this.state.homeserver === "" || this.state.username === "" || this.state.password === "") { + if (homeserver === "" || username === "" || password === "") { return; } - if (this.state.current_tab === "login" && !client?.isLoggedIn()) { - await client.login(this.state.homeserver, this.state.username, this.state.password, this.state.create_profile); - } else if (this.state.current_tab === "register" && !client.isLoggedIn()) { - await client.register(this.state.homeserver, this.state.username, this.state.password, this.state.create_profile); + if (currentTab === "login" && !client?.isLoggedIn()) { + await client.login(homeserver, username, password, createProfile); + } else if (currentTab === "register" && !client.isLoggedIn()) { + await client.register(homeserver, username, password, createProfile); } - this.props.navigate('/', { replace: true }); + navigate('/', { replace: true }); } - onInput(e: React.FormEvent) { + const onInput = (e: React.FormEvent) => { const target = (e.target as HTMLInputElement); const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; - this.setState({ [name]: value } as State); - } + switch (name) { + case "homeserver": + setHomeserver(value as string); + break; + case "username": + setUsername(value as string); + break; + case "password": + setPassword(value as string); + break; + case "createProfile": + setCreateProfile(value as boolean); + break; - render() { - const { homeserver, username, password, create_profile: create_account, current_tab } = this.state; - return ( - <div className="flex flex-col"> - <header> - <Header /> - </header> - - <main className="m-12 mt-6"> - <h1 className="text-3xl font-bold mb-4 text-white">Join</h1> - <div className="flex items-center flex-col"> - <ul className="w-1/4 mb-8 hidden text-sm font-medium text-center text-gray-500 rounded-lg divide-x divide-gray-200 shadow sm:flex dark:divide-gray-700 dark:text-gray-400"> - <li className="w-full"> - <a href="#" className={current_tab === "login" ? `${ACTIVE_TAB_CSS} rounded-l-lg` : `${TAB_CSS} rounded-l-lg`} onClick={(e) => { e.preventDefault(); this.setState({ current_tab: "login" }); }}>Login</a> - </li> - <li className="w-full"> - <a href="#" className={current_tab === "register" ? `${ACTIVE_TAB_CSS} rounded-r-lg` : `${TAB_CSS} rounded-r-lg`} onClick={(e) => { e.preventDefault(); this.setState({ current_tab: "register" }); }}>Register</a> - </li> - </ul> - <form onSubmit={this.onSubmit.bind(this)} className="flex flex-col items-start w-1/4"> - <input className="search-bg shadow rounded-lg border-0 py-3 px-4 placeholder-data text-white mb-4 w-full" type="url" placeholder="Homeserver" name="homeserver" value={homeserver} onInput={this.onInput.bind(this)} /> - <input className="search-bg shadow rounded-lg border-0 py-3 px-4 placeholder-data text-white mb-4 w-full" autoComplete="username" type="text" placeholder="Username" name="username" value={username} onInput={this.onInput.bind(this)} /> - <input className="search-bg shadow rounded-lg border-0 py-3 px-4 placeholder-data text-white mb-4 w-full" autoComplete="current-password" type="password" placeholder="Password" name="password" value={password} onInput={this.onInput.bind(this)} /> - <label className="mb-4 flex items-center"> - <input className="checked:bg-blue-600 checked:border-transparent checked:bg-no-repeat checked:bg-[url('/tick.svg')] outline-none focus:outline-offset-2 focus:ring-blue-600 focus:ring-offset-2 focus:ring-offset-white p-0 inline-block align-middle box-border select-none shrink-0 shadow h-5 w-5 appearance-none rounded bg-white border-none" type="checkbox" name="create_profile" checked={create_account} onChange={this.onInput.bind(this)} /> - <span className="ml-4 text-data text-base font-medium">Create account</span> - </label> - - <button type="submit" className="text-white font-bold text-lg logo-bg rounded-xl py-2 px-10 shadow transform transition-transform ease-in-out duration-300 hover:scale-105 w-1/2 self-center justify-center flex">{current_tab === "login" ? "Login" : "Register"}</button> - </form> - </div> - </main > - </div > - ); + default: + break; + } } -} + return ( + <div className="flex flex-col"> + <header> + <Header /> + </header> + + <main className="m-12 mt-6"> + <h1 className="text-3xl font-bold mb-4 text-white">Join</h1> + <div className="flex items-center flex-col"> + <ul className="w-1/4 mb-8 hidden text-sm font-medium text-center text-gray-500 rounded-lg divide-x divide-gray-200 shadow sm:flex dark:divide-gray-700 dark:text-gray-400"> + <li className="w-full"> + <a href="#" className={currentTab === "login" ? `${ACTIVE_TAB_CSS} rounded-l-lg` : `${TAB_CSS} rounded-l-lg`} onClick={(e) => { setCurrentTab("login"); }}>Login</a> + </li> + <li className="w-full"> + <a href="#" className={currentTab === "register" ? `${ACTIVE_TAB_CSS} rounded-r-lg` : `${TAB_CSS} rounded-r-lg`} onClick={(e) => { setCurrentTab("register"); }}>Register</a> + </li> + </ul> + <form onSubmit={onSubmit} className="flex flex-col items-start w-1/4"> + <input className="search-bg shadow rounded-lg border-0 py-3 px-4 placeholder-data text-white mb-4 w-full" type="url" placeholder="Homeserver" name="homeserver" value={homeserver} onInput={onInput} /> + <input className="search-bg shadow rounded-lg border-0 py-3 px-4 placeholder-data text-white mb-4 w-full" autoComplete="username" type="text" placeholder="Username" name="username" value={username} onInput={onInput} /> + <input className="search-bg shadow rounded-lg border-0 py-3 px-4 placeholder-data text-white mb-4 w-full" autoComplete="current-password" type="password" placeholder="Password" name="password" value={password} onInput={onInput} /> + <label className="mb-4 flex items-center"> + <input className="checked:bg-blue-600 checked:border-transparent checked:bg-no-repeat checked:bg-[url('/tick.svg')] outline-none focus:outline-offset-2 focus:ring-blue-600 focus:ring-offset-2 focus:ring-offset-white p-0 inline-block align-middle box-border select-none shrink-0 shadow h-5 w-5 appearance-none rounded bg-white border-none" type="checkbox" name="createProfile" checked={createProfile} onChange={onInput} /> + <span className="ml-4 text-data text-base font-medium">Create account</span> + </label> -Join.contextType = Client; -export default withNavigateHOC(Join); -\ No newline at end of file + <button type="submit" className="text-white font-bold text-lg logo-bg rounded-xl py-2 px-10 shadow transform transition-transform ease-in-out duration-300 hover:scale-105 w-1/2 self-center justify-center flex">{currentTab === "login" ? "Login" : "Register"}</button> + </form> + </div> + </main > + </div > + ); +} +\ No newline at end of file