diff --git a/packages/dashboard-v2/src/components/AvatarUploader/AvatarUploader.js b/packages/dashboard-v2/src/components/AvatarUploader/AvatarUploader.js new file mode 100644 index 00000000..9f5bbc82 --- /dev/null +++ b/packages/dashboard-v2/src/components/AvatarUploader/AvatarUploader.js @@ -0,0 +1,35 @@ +import { useEffect, useState } from "react"; + +import { useUser } from "../../contexts/user"; +import { SimpleUploadIcon } from "../Icons"; + +const AVATAR_PLACEHOLDER = "/images/avatar-placeholder.svg"; + +export const AvatarUploader = (props) => { + const { user } = useUser(); + const [imageUrl, setImageUrl] = useState(AVATAR_PLACEHOLDER); + + useEffect(() => { + setImageUrl(user.avatarUrl ?? AVATAR_PLACEHOLDER); + }, [user]); + + return ( +
+
+ +
+
+ + {/* TODO: actual uploading */} +
+
+ ); +}; diff --git a/packages/dashboard-v2/src/components/AvatarUploader/index.js b/packages/dashboard-v2/src/components/AvatarUploader/index.js new file mode 100644 index 00000000..74358cdc --- /dev/null +++ b/packages/dashboard-v2/src/components/AvatarUploader/index.js @@ -0,0 +1 @@ +export * from "./AvatarUploader"; diff --git a/packages/dashboard-v2/src/components/Button/Button.js b/packages/dashboard-v2/src/components/Button/Button.js index 95ecbede..40ec1ad9 100644 --- a/packages/dashboard-v2/src/components/Button/Button.js +++ b/packages/dashboard-v2/src/components/Button/Button.js @@ -6,7 +6,7 @@ import styled from "styled-components"; */ export const Button = styled.button.attrs(({ $primary }) => ({ type: "button", - className: `px-6 py-3 rounded-full font-sans uppercase text-xs tracking-wide text-palette-600 transition-[filter] hover:brightness-90 + className: `px-6 py-2.5 rounded-full font-sans uppercase text-xs tracking-wide text-palette-600 transition-[filter] hover:brightness-90 ${$primary ? "bg-primary" : "bg-white border-2 border-black"}`, }))``; Button.propTypes = { diff --git a/packages/dashboard-v2/src/components/CopyButton.js b/packages/dashboard-v2/src/components/CopyButton.js index db5e9c21..479352d2 100644 --- a/packages/dashboard-v2/src/components/CopyButton.js +++ b/packages/dashboard-v2/src/components/CopyButton.js @@ -22,7 +22,7 @@ const TooltipContent = styled.div.attrs({ className: "bg-primary-light/10 text-palette-600 py-2 px-4 ", })``; -export const CopyButton = ({ value }) => { +export const CopyButton = ({ value, className }) => { const containerRef = useRef(); const [copied, setCopied] = useState(false); const [timer, setTimer] = useState(null); @@ -32,13 +32,13 @@ export const CopyButton = ({ value }) => { copy(value); setCopied(true); - setTimer(setTimeout(() => setCopied(false), 150000)); + setTimer(setTimeout(() => setCopied(false), 1500)); }, [value, timer]); useClickAway(containerRef, () => setCopied(false)); return ( -
+
diff --git a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js index 461a9b7e..86cbad5f 100644 --- a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js +++ b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenu.js @@ -30,7 +30,7 @@ const TriggerIcon = styled(ChevronDownIcon).attrs({ `; const Flyout = styled.div.attrs(({ open }) => ({ - className: `absolute top-full right-0 p-0 + className: `absolute top-full right-0 p-0 z-10 border rounded border-palette-100 bg-white shadow-md shadow-palette-200/50 ${open ? "visible" : "invisible"}`, diff --git a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js index 45a86483..426501c4 100644 --- a/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js +++ b/packages/dashboard-v2/src/components/DropdownMenu/DropdownMenuLink.js @@ -3,18 +3,16 @@ import PropTypes from "prop-types"; const DropdownLink = styled.a.attrs({ className: `m-0 border-t border-palette-200/50 h-[60px] - whitespace-nowrap transition-colors text-current + whitespace-nowrap transition-colors hover:bg-palette-100/50 flex items-center pr-8 pl-6 py-4 gap-4 first:border-0`, })``; export const DropdownMenuLink = ({ active, icon: Icon, label, ...props }) => ( - <> - - {Icon ? : null} - {label} - - + + {Icon ? : null} + {label} + ); DropdownMenuLink.propTypes = { diff --git a/packages/dashboard-v2/src/components/Icons/icons/SimpleUploadIcon.js b/packages/dashboard-v2/src/components/Icons/icons/SimpleUploadIcon.js new file mode 100644 index 00000000..0406f012 --- /dev/null +++ b/packages/dashboard-v2/src/components/Icons/icons/SimpleUploadIcon.js @@ -0,0 +1,10 @@ +import { withIconProps } from "../withIconProps"; + +export const SimpleUploadIcon = withIconProps(({ size, ...props }) => ( + + + +)); diff --git a/packages/dashboard-v2/src/components/Icons/index.js b/packages/dashboard-v2/src/components/Icons/index.js index 05d9b832..611acef4 100644 --- a/packages/dashboard-v2/src/components/Icons/index.js +++ b/packages/dashboard-v2/src/components/Icons/index.js @@ -12,3 +12,4 @@ export * from "./icons/PlusIcon"; export * from "./icons/SearchIcon"; export * from "./icons/CopyIcon"; export * from "./icons/ShareIcon"; +export * from "./icons/SimpleUploadIcon"; diff --git a/packages/dashboard-v2/src/components/NavBar/NavBar.js b/packages/dashboard-v2/src/components/NavBar/NavBar.js index 2b53f2be..1db72dda 100644 --- a/packages/dashboard-v2/src/components/NavBar/NavBar.js +++ b/packages/dashboard-v2/src/components/NavBar/NavBar.js @@ -9,7 +9,7 @@ import { PageContainer } from "../PageContainer"; import { NavBarLink, NavBarSection } from "."; const NavBarContainer = styled.div.attrs({ - className: `grid sticky top-0 bg-white`, + className: `grid sticky top-0 bg-white z-10 shadow-sm`, })``; const NavBarBody = styled.nav.attrs({ @@ -68,8 +68,21 @@ export const NavBar = () => ( - - + + diff --git a/packages/dashboard-v2/src/components/Switch/Switch.js b/packages/dashboard-v2/src/components/Switch/Switch.js index ed24bc92..892692be 100644 --- a/packages/dashboard-v2/src/components/Switch/Switch.js +++ b/packages/dashboard-v2/src/components/Switch/Switch.js @@ -21,7 +21,7 @@ const Label = styled.label.attrs({ `; const Toggle = styled.span.attrs({ - className: `flex flex-row items-center justify-between + className: `flex flex-row items-center justify-between shrink-0 w-[44px] h-[22px] bg-white rounded-full border border-palette-200 relative cursor-pointer`, })` @@ -45,7 +45,7 @@ const TogglePin = styled.span.attrs(({ $checked }) => ({ } `; -export const Switch = ({ children, defaultChecked, onChange, ...props }) => { +export const Switch = ({ children, defaultChecked, labelClassName, onChange, ...props }) => { const id = useMemo(nanoid, [onChange]); const [checked, setChecked] = useState(defaultChecked); @@ -56,11 +56,11 @@ export const Switch = ({ children, defaultChecked, onChange, ...props }) => { return ( setChecked(ev.target.checked)} id={id} /> - ); @@ -74,7 +74,11 @@ Switch.propTypes = { /** * Element to be rendered as the switch label */ - children: PropTypes.element, + children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]), + /** + * Pass additional CSS classes to the `label` element. + */ + labelClassName: PropTypes.string, /** * Function to execute on change */ @@ -83,4 +87,5 @@ Switch.propTypes = { Switch.defaultProps = { defaultChecked: false, + labelClassName: "", }; diff --git a/packages/dashboard-v2/src/components/TextInputBasic/TextInputBasic.js b/packages/dashboard-v2/src/components/TextInputBasic/TextInputBasic.js index 9fa7f670..6b9531b4 100644 --- a/packages/dashboard-v2/src/components/TextInputBasic/TextInputBasic.js +++ b/packages/dashboard-v2/src/components/TextInputBasic/TextInputBasic.js @@ -1,18 +1,20 @@ +import { nanoid } from "nanoid"; import PropTypes from "prop-types"; +import { useMemo } from "react"; + +export const TextInputBasic = ({ label, placeholder, ...props }) => { + const id = useMemo(() => `input-${nanoid()}`, []); -/** - * Primary UI component for user interaction - */ -export const TextInputBasic = ({ label, placeholder }) => { return ( -
-

{label}

+
+
); diff --git a/packages/dashboard-v2/src/layouts/UserSettingsLayout.js b/packages/dashboard-v2/src/layouts/UserSettingsLayout.js new file mode 100644 index 00000000..9fda613d --- /dev/null +++ b/packages/dashboard-v2/src/layouts/UserSettingsLayout.js @@ -0,0 +1,87 @@ +import * as React from "react"; +import { Link } from "gatsby"; +import styled from "styled-components"; +import { SWRConfig } from "swr"; + +import { authenticatedOnly } from "../lib/swrConfig"; + +import { PageContainer } from "../components/PageContainer"; +import { NavBar } from "../components/Navbar"; +import { Footer } from "../components/Footer"; +import { UserProvider, useUser } from "../contexts/user"; +import { ContainerLoadingIndicator } from "../components/LoadingIndicator"; + +const Wrapper = styled.div.attrs({ + className: "min-h-screen overflow-hidden", +})` + background-image: url(/images/dashboard-bg.svg); + background-position: center -280px; + background-repeat: no-repeat; +`; + +const Layout = ({ children }) => { + const { user } = useUser(); + + // Prevent from flashing the dashboard screen to unauthenticated users. + return ( + + {!user && ( +
+ +
+ )} + {user && <>{children}} +
+ ); +}; + +const Sidebar = () => ( + +); + +const SidebarLink = styled(Link).attrs({ + className: `h-12 py-3 px-6 h-full w-full flex + border-l-2 border-l-palette-200 + border-b border-b-palette-100 last:border-b-transparent`, +})``; + +const Content = styled.main.attrs({ + className: "relative bg-white rounded px-6 py-6 sm:px-16 sm:py-14 mt-6 lg:mt-0 bg-none xl:bg-corner-circle", +})` + background-repeat: no-repeat; +`; + +const UserSettingsLayout = ({ children }) => ( + + + + + +
Settings
+
+ + {children} +
+
+