Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 13 additions & 34 deletions src/layout/Footer.jsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,21 @@
import { Box, Grid, GridItem } from "@chakra-ui/react";
import { Box, Grid, GridItem, Link, IconButton } from "@chakra-ui/react";
import { FaGithub, FaTwitter } from "react-icons/fa";
import MessageForm from "../components/MessageForm";

export default function Footer() {
return (
<Box position="fixed" bottom="0" width="100%">
<Box
position="fixed"
bottom="0"
width="100%"
bg="white"
boxShadow="md"
py={2}
px={4}
>
<MessageForm />

<Grid
gridTemplateColumns="auto 1fr"
textAlign="center"
alignItems="center"
py="4px"
px="30px"
height="40px"
bg="white"
>
<GridItem justifySelf="start">
{/* Built by{" "} */}
{/* <a href="http://shimon-wosner.vercel.app" target="_blank"> */}
<a
href="https://twitter.com/shwosner"
target="_blank"
rel="noreferrer"
>
<FaTwitter style={{ display: "inline" }} />
@shwosner
</a>
</GridItem>
<GridItem justifySelf="end">
<a
href="https://github.com/shwosner/realtime-chat-supabase-react"
target="_blank"
rel="noreferrer"
>
<FaGithub style={{ display: "inline" }} /> Source code
</a>
</GridItem>
</Grid>


</Box>
);
}
178 changes: 125 additions & 53 deletions src/layout/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,140 @@
import { Button, Grid, GridItem, Image } from "@chakra-ui/react";
import { FaGithub } from "react-icons/fa";
import { Button, Grid, GridItem, Image, Box, Text, IconButton, Input, Stack } from "@chakra-ui/react";
import { FaSignOutAlt } from "react-icons/fa";
import { BiSave, BiEdit } from "react-icons/bi";
import { useEffect, useRef, useState } from "react";
import supabase from "../supabaseClient";

import { useAppContext } from "../context/appContext";
import NameForm from "./NameForm";

function NameForm() {
const { username, setUsername } = useAppContext();
const [newUsername, setNewUsername] = useState(username);
const [isEditing, setIsEditing] = useState(false);
const inputRef = useRef(null);

useEffect(() => {
if (isEditing) {
inputRef.current.focus();
}
}, [isEditing]);

useEffect(() => {
setNewUsername(username);
}, [username]);

const handleSubmit = (e) => {
e.preventDefault();
setIsEditing(false);

if (!newUsername) {
setNewUsername(username);
return;
}

setUsername(newUsername);
localStorage.setItem("username", newUsername);
};

return (
<form onSubmit={handleSubmit}>
<Stack direction="row" alignItems="center">
{isEditing ? (
<Input
name="username"
placeholder="Enter your username"
onChange={(e) => setNewUsername(e.target.value)}
value={newUsername}
bg="gray.100"
size="sm"
borderRadius="md"
borderColor="gray.300"
focusBorderColor="teal.500"
ref={inputRef}
maxLength="15"
onBlur={handleSubmit}
/>
) : (
<Text
fontSize="md"
fontWeight="medium"
color="gray.700"
cursor="pointer"
_hover={{ color: "teal.500" }}
onClick={() => setIsEditing(true)}
>
Welcome, <strong>{newUsername}</strong>
</Text>
)}
<IconButton
size="sm"
colorScheme="teal"
variant="outline"
aria-label={isEditing ? "Save" : "Edit"}
icon={isEditing ? <BiSave /> : <BiEdit />}
onClick={(e) => {
if (isEditing) {
handleSubmit(e);
} else setIsEditing(true);
}}
/>
</Stack>
</form>
);
}

export default function Header() {
const { username, setUsername, randomUsername, session } = useAppContext();

return (
<Grid
templateColumns="max-content 1fr min-content"
justifyItems="center"
alignItems="center"
<Box
as="header"
bg="white"
position="sticky"
top="0"
zIndex="10"
borderBottom="20px solid #edf2f7"
boxShadow="lg"
py={4}
px={8}
borderBottom="4px solid #e2e8f0"
>
<GridItem justifySelf="start" m="2">
<Image src="/logo.png" height="30px" ml="2" />
</GridItem>
{session ? (
<>
<GridItem justifySelf="end" alignSelf="center" mr="4">
Welcome <strong>{username}</strong>
</GridItem>
<Button
marginRight="4"
size="sm"
variant="link"
onClick={() => {
const { error } = supabase.auth.signOut();
if (error) return console.error("error signOut", error);
const username = randomUsername();
setUsername(username);
localStorage.setItem("username", username);
}}
>
Log out
</Button>
</>
) : (
<>
<GridItem justifySelf="end" alignSelf="end">
<Grid
templateColumns="max-content 1fr auto"
alignItems="center"
gap={6}
>
<GridItem>
<Image src="/logo.png" height="50px" alt="Logo" />
</GridItem>

{session ? (
<>
<GridItem justifySelf="center">
<Text fontSize="xl" fontWeight="bold" color="gray.700">
Welcome, {username}!
</Text>
</GridItem>
<GridItem>
<IconButton
size="md"
colorScheme="red"
variant="solid"
aria-label="Logout"
icon={<FaSignOutAlt />}
onClick={() => {
const { error } = supabase.auth.signOut();
if (error) return console.error("error signOut", error);
const username = randomUsername();
setUsername(username);
localStorage.setItem("username", username);
}}
/>
</GridItem>
</>
) : (
<GridItem>
<NameForm username={username} setUsername={setUsername} />
</GridItem>
<Button
size="sm"
marginRight="2"
colorScheme="teal"
rightIcon={<FaGithub />}
variant="outline"
onClick={() =>
supabase.auth.signInWithOAuth({
provider: "github",
redirectTo: window.location.origin,
})
}
>
Login
</Button>
</>
)}
</Grid>
)}
</Grid>
</Box>
);
}
Loading