Redesign homepage WIP

This commit is contained in:
Robert Long
2022-01-04 16:00:13 -08:00
parent eb620e9220
commit ef8c28f274
18 changed files with 697 additions and 437 deletions

131
src/home/RegisteredView.jsx Normal file
View File

@@ -0,0 +1,131 @@
import React from "react";
import { Link } from "react-router-dom";
import {
useGroupCallRooms,
usePublicRooms,
} from "../ConferenceCallManagerHooks";
import { Header, HeaderLogo, LeftNav, RightNav } from "../Header";
import styles from "../Home.module.css";
import { FieldRow, InputField, ErrorMessage } from "../Input";
import { Button } from "../button";
import { CallList } from "../CallList";
import classNames from "classnames";
import { UserMenuContainer } from "../UserMenuContainer";
export function RegisteredView({
client,
isPasswordlessUser,
onCreateRoom,
createRoomError,
creatingRoom,
onJoinRoom,
}) {
const publicRooms = usePublicRooms(
client,
import.meta.env.VITE_PUBLIC_SPACE_ROOM_ID
);
const recentRooms = useGroupCallRooms(client);
const hideCallList = publicRooms.length === 0 && recentRooms.length === 0;
return (
<div
className={classNames(styles.home, {
[styles.fullWidth]: hideCallList,
})}
>
<Header className={styles.header}>
<LeftNav className={styles.leftNav}>
<HeaderLogo />
</LeftNav>
<RightNav>
<UserMenuContainer />
</RightNav>
</Header>
<div className={styles.splitContainer}>
<div className={styles.left}>
<div className={styles.content}>
<div className={styles.centered}>
<form onSubmit={onJoinRoom}>
<h1>Join a call</h1>
<FieldRow className={styles.fieldRow}>
<InputField
id="roomId"
name="roomId"
label="Call ID"
type="text"
required
autoComplete="off"
placeholder="Call ID"
/>
</FieldRow>
<FieldRow className={styles.fieldRow}>
<Button className={styles.button} type="submit">
Join call
</Button>
</FieldRow>
</form>
<hr />
<form onSubmit={onCreateRoom}>
<h1>Create a call</h1>
<FieldRow className={styles.fieldRow}>
<InputField
id="roomName"
name="roomName"
label="Room Name"
type="text"
required
autoComplete="off"
placeholder="Room Name"
/>
</FieldRow>
{createRoomError && (
<FieldRow className={styles.fieldRow}>
<ErrorMessage>{createRoomError.message}</ErrorMessage>
</FieldRow>
)}
<FieldRow className={styles.fieldRow}>
<Button
className={styles.button}
type="submit"
disabled={creatingRoom}
>
{creatingRoom ? "Creating call..." : "Create call"}
</Button>
</FieldRow>
</form>
{isPasswordlessUser && (
<div className={styles.authLinks}>
<p>
Not registered yet?{" "}
<Link to="/register">Create an account</Link>
</p>
</div>
)}
</div>
</div>
</div>
{!hideCallList && (
<div className={styles.right}>
<div className={styles.content}>
{publicRooms.length > 0 && (
<CallList
title="Public Calls"
rooms={publicRooms}
client={client}
/>
)}
{recentRooms.length > 0 && (
<CallList
title="Recent Calls"
rooms={recentRooms}
client={client}
/>
)}
</div>
</div>
)}
</div>
</div>
);
}

View File

@@ -0,0 +1,154 @@
import React, { useCallback, useState } from "react";
import { Header, HeaderLogo, LeftNav, RightNav } from "../Header";
import { UserMenuContainer } from "../UserMenuContainer";
import { useHistory } from "react-router-dom";
import { FieldRow, InputField, ErrorMessage } from "../Input";
import { Button } from "../button";
import { randomString } from "matrix-js-sdk/src/randomstring";
import {
createRoom,
useInteractiveRegistration,
} from "../ConferenceCallManagerHooks";
import { useModalTriggerState } from "../Modal";
import { JoinExistingCallModal } from "../JoinExistingCallModal";
import { useRecaptcha } from "../useRecaptcha";
import { Body, Caption, Title, Link, Headline } from "../typography/Typography";
import { Form } from "../form/Form";
import styles from "./UnauthenticatedView.module.css";
export function UnauthenticatedView() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState();
const [{ privacyPolicyUrl, recaptchaKey }, register] =
useInteractiveRegistration();
const { execute, reset, recaptchaId } = useRecaptcha(recaptchaKey);
const onSubmit = useCallback(
(e) => {
e.preventDefault();
const data = new FormData(e.target);
const roomName = data.get("roomName");
const userName = data.get("userName");
async function submit() {
setError(undefined);
setLoading(true);
const recaptchaResponse = await execute();
const client = await register(
userName,
randomString(16),
recaptchaResponse,
true
);
const roomIdOrAlias = await createRoom(client, roomName);
if (roomIdOrAlias) {
history.push(`/room/${roomIdOrAlias}`);
}
}
submit().catch((error) => {
if (error.errcode === "M_ROOM_IN_USE") {
setExistingRoomId(roomAliasFromRoomName(roomName));
setError(undefined);
modalState.open();
} else {
console.error(error);
setLoading(false);
setError(error);
reset();
}
});
},
[register]
);
const { modalState, modalProps } = useModalTriggerState();
const [existingRoomId, setExistingRoomId] = useState();
const history = useHistory();
const onJoinExistingRoom = useCallback(() => {
history.push(`/${existingRoomId}`);
}, [history, existingRoomId]);
return (
<>
<Header>
<LeftNav>
<HeaderLogo />
</LeftNav>
<RightNav hideMobile>
<UserMenuContainer />
</RightNav>
</Header>
<div className={styles.container}>
<main className={styles.main}>
<HeaderLogo className={styles.logo} />
<Headline className={styles.headline}>Enter a call name</Headline>
<Form className={styles.form} onSubmit={onSubmit}>
<FieldRow>
<InputField
id="callName"
name="callName"
label="Call name"
placeholder="Call name"
type="text"
required
autoComplete="off"
/>
</FieldRow>
<FieldRow>
<InputField
id="userName"
name="userName"
label="Your name"
placeholder="Your name"
type="text"
required
autoComplete="off"
/>
</FieldRow>
<Caption>
This site is protected by ReCAPTCHA and the Google{" "}
<Link href="https://www.google.com/policies/privacy/">
Privacy Policy
</Link>{" "}
and{" "}
<Link href="https://policies.google.com/terms">
Terms of Service
</Link>{" "}
apply.
<br />
By clicking "Go", you agree to our{" "}
<Link href={privacyPolicyUrl}>Terms and conditions</Link>
</Caption>
{error && (
<FieldRow>
<ErrorMessage>{error.message}</ErrorMessage>
</FieldRow>
)}
<Button type="submit" size="lg" disabled={loading}>
{loading ? "Loading..." : "Go"}
</Button>
<div id={recaptchaId} />
</Form>
</main>
<footer className={styles.footer}>
<Body className={styles.mobileLoginLink}>
<Link color="primary" to="/l;ogin">
Login to your account
</Link>
</Body>
<Body>
Not registered yet?{" "}
<Link color="primary" to="/register">
Create an account
</Link>
</Body>
</footer>
</div>
{modalState.isOpen && (
<JoinExistingCallModal onJoin={onJoinExistingRoom} {...modalProps} />
)}
</>
);
}

View File

@@ -0,0 +1,63 @@
.container {
display: flex;
min-height: calc(100% - 64px);
flex-direction: column;
justify-content: space-between;
}
.main {
display: flex;
flex: 1;
flex-direction: column;
align-items: center;
justify-content: center;
}
.footer {
display: flex;
flex-direction: column;
align-items: center;
padding: 28px;
}
.footer p {
margin-bottom: 0;
}
.footer .mobileLoginLink {
display: flex;
margin-bottom: 24px;
}
.logo {
display: flex;
margin-bottom: 54px;
}
.headline {
margin-bottom: 40px;
}
.form {
padding: 0 24px;
justify-content: center;
max-width: 360px;
}
.form > * + * {
margin-bottom: 24px;
}
@media (min-width: 800px) {
.logo {
display: none;
}
.mobileLoginLink {
display: none;
}
.container {
min-height: calc(100% - 76px);
}
}