style: responsive profile (#3596)

* style: responsive profile

* style: profile header drop down, sidebar auto show hide depending on the screen width

* fix: item tap on white space in the drop down menu in profile header

* fix: profile layout breaking on big screens in page visit
This commit is contained in:
Ramesh Kumar Chandra 2024-02-08 17:49:26 +05:30 committed by GitHub
parent 9545dc77d6
commit 55afef204d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 571 additions and 369 deletions

View File

@ -1,18 +1,78 @@
// ui
import { Breadcrumbs } from "@plane/ui";
import { Breadcrumbs, CustomMenu } from "@plane/ui";
import { BreadcrumbLink } from "components/common";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
import { cn } from "helpers/common.helper";
import { FC } from "react";
import { useApplication, useUser } from "hooks/store";
import { ChevronDown, PanelRight } from "lucide-react";
import { observer } from "mobx-react-lite";
import { PROFILE_ADMINS_TAB, PROFILE_VIEWER_TAB } from "constants/profile";
import Link from "next/link";
import { useRouter } from "next/router";
export const UserProfileHeader = () => (
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
type TUserProfileHeader = {
type?: string | undefined
}
export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
const { type = undefined } = props
const router = useRouter();
const { workspaceSlug, userId } = router.query;
const AUTHORIZED_ROLES = [20, 15, 10];
const {
membership: { currentWorkspaceRole },
} = useUser();
if (!currentWorkspaceRole) return null;
const isAuthorized = AUTHORIZED_ROLES.includes(currentWorkspaceRole);
const tabsList = isAuthorized ? [...PROFILE_VIEWER_TAB, ...PROFILE_ADMINS_TAB] : PROFILE_VIEWER_TAB;
const { theme: themStore } = useApplication();
return (<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle />
<div>
<div className="flex justify-between w-full">
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem type="text" link={<BreadcrumbLink href="/profile" label="Activity Overview" />} />
</Breadcrumbs>
<div className="flex gap-4 md:hidden">
<CustomMenu
maxHeight={"md"}
className="flex flex-grow justify-center text-custom-text-200 text-sm"
placement="bottom-start"
customButton={
<div className="flex gap-2 items-center px-2 py-1.5 border border-custom-border-400 rounded-md">
<span className="flex flex-grow justify-center text-custom-text-200 text-sm">{type}</span>
<ChevronDown className="w-4 h-4 text-custom-text-400" />
</div>
}
customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
closeOnSelect
>
<></>
{tabsList.map((tab) => (
<CustomMenu.MenuItem
className="flex items-center gap-2"
>
<Link key={tab.route} href={`/${workspaceSlug}/profile/${userId}/${tab.route}`} className="text-custom-text-300 w-full">{tab.label}</Link>
</CustomMenu.MenuItem>
))}
</CustomMenu>
<button className="transition-all block md:hidden" onClick={() => { themStore.toggleProfileSidebar(); console.log(themStore.profileSidebarCollapsed) }}>
<PanelRight className={
cn("w-4 h-4 block md:hidden", !themStore.profileSidebarCollapsed ? "text-[#3E63DD]" : "text-custom-text-200")
} />
</button>
</div>
</div>
</div>
);
</div>)
});

View File

@ -22,13 +22,12 @@ export const ProfileNavbar: React.FC<Props> = (props) => {
const tabsList = isAuthorized ? [...PROFILE_VIEWER_TAB, ...PROFILE_ADMINS_TAB] : PROFILE_VIEWER_TAB;
return (
<div className="sticky -top-0.5 z-10 flex items-center justify-between gap-4 border-b border-custom-border-300 bg-custom-background-100 px-4 sm:px-5 md:static">
<div className="sticky -top-0.5 z-10 hidden md:flex items-center justify-between gap-4 border-b border-custom-border-300 bg-custom-background-100 px-4 sm:px-5 md:static">
<div className="flex items-center overflow-x-scroll">
{tabsList.map((tab) => (
<Link key={tab.route} href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}>
<span
className={`flex whitespace-nowrap border-b-2 p-4 text-sm font-medium outline-none ${
router.pathname === tab.selected
className={`flex whitespace-nowrap border-b-2 p-4 text-sm font-medium outline-none ${router.pathname === tab.selected
? "border-custom-primary-100 text-custom-primary-100"
: "border-transparent"
}`}

View File

@ -4,7 +4,7 @@ import useSWR from "swr";
import { Disclosure, Transition } from "@headlessui/react";
import { observer } from "mobx-react-lite";
// hooks
import { useUser } from "hooks/store";
import { useApplication, useUser } from "hooks/store";
// services
import { UserService } from "services/user.service";
// components
@ -18,6 +18,8 @@ import { renderFormattedDate } from "helpers/date-time.helper";
import { renderEmoji } from "helpers/emoji.helper";
// fetch-keys
import { USER_PROFILE_PROJECT_SEGREGATION } from "constants/fetch-keys";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { useEffect, useRef } from "react";
// services
const userService = new UserService();
@ -28,6 +30,8 @@ export const ProfileSidebar = observer(() => {
const { workspaceSlug, userId } = router.query;
// store hooks
const { currentUser } = useUser();
const { theme: themStore } = useApplication();
const ref = useRef<HTMLDivElement>(null);
const { data: userProjectsData } = useSWR(
workspaceSlug && userId ? USER_PROFILE_PROJECT_SEGREGATION(workspaceSlug.toString(), userId.toString()) : null,
@ -36,6 +40,14 @@ export const ProfileSidebar = observer(() => {
: null
);
useOutsideClickDetector(ref, () => {
if (themStore.profileSidebarCollapsed === false) {
if (window.innerWidth < 768) {
themStore.toggleProfileSidebar();
}
}
});
const userDetails = [
{
label: "Joined on",
@ -47,8 +59,26 @@ export const ProfileSidebar = observer(() => {
},
];
useEffect(() => {
const handleToggleProfileSidebar = () => {
if (window && window.innerWidth < 768) {
themStore.toggleProfileSidebar(true);
}
if (window && themStore.profileSidebarCollapsed && window.innerWidth >= 768) {
themStore.toggleProfileSidebar(false);
}
};
window.addEventListener("resize", handleToggleProfileSidebar);
handleToggleProfileSidebar();
return () => window.removeEventListener("resize", handleToggleProfileSidebar);
}, [themStore]);
return (
<div className="w-full flex-shrink-0 overflow-y-auto shadow-custom-shadow-sm md:h-full md:w-80 border-l border-custom-border-100">
<div
className={`flex-shrink-0 overflow-hidden overflow-y-auto shadow-custom-shadow-sm border-l border-custom-border-100 bg-custom-sidebar-background-100 h-full z-[5] fixed md:relative transition-all w-full md:w-[300px]`}
style={themStore.profileSidebarCollapsed ? { marginLeft: `${window?.innerWidth || 0}px` } : {}}
>
{userProjectsData ? (
<>
<div className="relative h-32">
@ -132,8 +162,7 @@ export const ProfileSidebar = observer(() => {
{project.assigned_issues > 0 && (
<Tooltip tooltipContent="Completion percentage" position="left">
<div
className={`rounded px-1 py-0.5 text-xs font-medium ${
completedIssuePercentage <= 35
className={`rounded px-1 py-0.5 text-xs font-medium ${completedIssuePercentage <= 35
? "bg-red-500/10 text-red-500"
: completedIssuePercentage <= 70
? "bg-yellow-500/10 text-yellow-500"

View File

@ -2,6 +2,11 @@ import { FC, ReactNode } from "react";
// layout
import { ProfileSettingsLayout } from "layouts/settings-layout";
import { ProfilePreferenceSettingsSidebar } from "./sidebar";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
import { CustomMenu } from "@plane/ui";
import { ChevronDown } from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/router";
interface IProfilePreferenceSettingsLayout {
children: ReactNode;
@ -10,9 +15,57 @@ interface IProfilePreferenceSettingsLayout {
export const ProfilePreferenceSettingsLayout: FC<IProfilePreferenceSettingsLayout> = (props) => {
const { children, header } = props;
const router = useRouter();
const showMenuItem = () => {
const item = router.asPath.split('/');
let splittedItem = item[item.length - 1];
splittedItem = splittedItem.replace(splittedItem[0], splittedItem[0].toUpperCase());
console.log(splittedItem);
return splittedItem;
}
const profilePreferenceLinks: Array<{
label: string;
href: string;
}> = [
{
label: "Theme",
href: `/profile/preferences/theme`,
},
{
label: "Email",
href: `/profile/preferences/email`,
},
];
return (
<ProfileSettingsLayout>
<ProfileSettingsLayout header={
<div className="md:hidden flex flex-shrink-0 gap-4 items-center justify-start border-b border-custom-border-200 p-4">
<SidebarHamburgerToggle />
<CustomMenu
maxHeight={"md"}
className="flex flex-grow justify-center text-custom-text-200 text-sm"
placement="bottom-start"
customButton={
<div className="flex gap-2 items-center px-2 py-1.5 border rounded-md border-custom-border-400">
<span className="flex flex-grow justify-center text-custom-text-200 text-sm">{showMenuItem()}</span>
<ChevronDown className="w-4 h-4 text-custom-text-400" />
</div>
}
customButtonClassName="flex flex-grow justify-start text-custom-text-200 text-sm"
>
<></>
{profilePreferenceLinks.map((link) => (
<CustomMenu.MenuItem
className="flex items-center gap-2"
>
<Link key={link.href} href={link.href} className="text-custom-text-300 w-full">{link.label}</Link>
</CustomMenu.MenuItem>
))}
</CustomMenu>
</div>
}>
<div className="relative flex h-screen w-full overflow-hidden">
<ProfilePreferenceSettingsSidebar />
<main className="relative flex h-full w-full flex-col overflow-hidden bg-custom-background-100">

View File

@ -19,15 +19,14 @@ export const ProfilePreferenceSettingsSidebar = () => {
},
];
return (
<div className="flex w-96 flex-col gap-6 px-8 py-12">
<div className="hidden md:flex w-96 flex-col gap-6 px-8 py-12">
<div className="flex flex-col gap-4">
<span className="text-xs font-semibold text-custom-text-400">Preference</span>
<div className="flex w-full flex-col gap-2">
{profilePreferenceLinks.map((link) => (
<Link key={link.href} href={link.href}>
<div
className={`rounded-md px-4 py-2 text-sm font-medium ${
(link.label === "Import" ? router.asPath.includes(link.href) : router.asPath === link.href)
className={`rounded-md px-4 py-2 text-sm font-medium ${(link.label === "Import" ? router.asPath.includes(link.href) : router.asPath === link.href)
? "bg-custom-primary-100/10 text-custom-primary-100"
: "text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
}`}

View File

@ -1,4 +1,4 @@
import { useState } from "react";
import { useEffect, useRef, useState } from "react";
import { mutate } from "swr";
import Link from "next/link";
import { useRouter } from "next/router";
@ -12,6 +12,7 @@ import useToast from "hooks/use-toast";
import { Tooltip } from "@plane/ui";
// constants
import { PROFILE_ACTION_LINKS } from "constants/profile";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
const WORKSPACE_ACTION_LINKS = [
{
@ -52,6 +53,35 @@ export const ProfileLayoutSidebar = observer(() => {
currentUserSettings?.workspace?.fallback_workspace_slug ||
"";
const ref = useRef<HTMLDivElement>(null);
useOutsideClickDetector(ref, () => {
if (sidebarCollapsed === false) {
if (window.innerWidth < 768) {
toggleSidebar();
}
}
});
useEffect(() => {
const handleResize = () => {
if (window.innerWidth <= 768) {
toggleSidebar(true);
}
};
handleResize();
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, [toggleSidebar]);
const handleItemClick = () => {
if (window.innerWidth < 768) {
toggleSidebar();
}
};
const handleSignOut = async () => {
setIsSigningOut(true);
@ -73,15 +103,17 @@ export const ProfileLayoutSidebar = observer(() => {
return (
<div
className={`fixed inset-y-0 z-20 flex h-full flex-shrink-0 flex-grow-0 flex-col border-r border-custom-sidebar-border-200 bg-custom-sidebar-background-100 duration-300 md:relative ${
sidebarCollapsed ? "" : "md:w-[280px]"
} ${sidebarCollapsed ? "left-0" : "-left-full md:left-0"}`}
className={`fixed inset-y-0 z-20 flex h-full flex-shrink-0 flex-grow-0 flex-col border-r border-custom-sidebar-border-200 bg-custom-sidebar-background-100 duration-300 md:relative
${sidebarCollapsed ? "-ml-[280px]" : ""}
sm:${sidebarCollapsed ? "-ml-[280px]" : ""}
md:ml-0 ${sidebarCollapsed ? "w-[80px]" : "w-[280px]"}
lg:ml-0 ${sidebarCollapsed ? "w-[80px]" : "w-[280px]"}
`}
>
<div className="flex h-full w-full flex-col gap-y-4">
<div ref={ref} className="flex h-full w-full flex-col gap-y-4">
<Link href={`/${redirectWorkspaceSlug}`}>
<div
className={`flex flex-shrink-0 items-center gap-2 truncate px-4 pt-4 ${
sidebarCollapsed ? "justify-center" : ""
className={`flex flex-shrink-0 items-center gap-2 truncate px-4 pt-4 ${sidebarCollapsed ? "justify-center" : ""
}`}
>
<span className="grid h-5 w-5 flex-shrink-0 place-items-center">
@ -101,11 +133,10 @@ export const ProfileLayoutSidebar = observer(() => {
if (link.key === "change-password" && currentUser?.is_password_autoset) return null;
return (
<Link key={link.key} href={link.href} className="block w-full">
<Link key={link.key} href={link.href} className="block w-full" onClick={handleItemClick}>
<Tooltip tooltipContent={link.label} position="right" className="ml-2" disabled={!sidebarCollapsed}>
<div
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium outline-none ${
link.highlight(router.pathname)
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium outline-none ${link.highlight(router.pathname)
? "bg-custom-primary-100/10 text-custom-primary-100"
: "text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80"
} ${sidebarCollapsed ? "justify-center" : ""}`}
@ -129,18 +160,16 @@ export const ProfileLayoutSidebar = observer(() => {
<Link
key={workspace.id}
href={`/${workspace.slug}`}
className={`flex flex-grow cursor-pointer select-none items-center truncate text-left text-sm font-medium ${
sidebarCollapsed ? "justify-center" : `justify-between`
className={`flex flex-grow cursor-pointer select-none items-center truncate text-left text-sm font-medium ${sidebarCollapsed ? "justify-center" : `justify-between`
}`}
onClick={handleItemClick}
>
<span
className={`flex w-full flex-grow items-center gap-x-2 truncate rounded-md px-3 py-1 hover:bg-custom-sidebar-background-80 ${sidebarCollapsed ? "justify-center" : ""
}`}
>
<span
className={`flex w-full flex-grow items-center gap-x-2 truncate rounded-md px-3 py-1 hover:bg-custom-sidebar-background-80 ${
sidebarCollapsed ? "justify-center" : ""
}`}
>
<span
className={`relative flex h-6 w-6 flex-shrink-0 items-center justify-center p-2 text-xs uppercase ${
!workspace?.logo && "rounded bg-custom-primary-500 text-white"
className={`relative flex h-6 w-6 flex-shrink-0 items-center justify-center p-2 text-xs uppercase ${!workspace?.logo && "rounded bg-custom-primary-500 text-white"
}`}
>
{workspace?.logo && workspace.logo !== "" ? (
@ -163,11 +192,10 @@ export const ProfileLayoutSidebar = observer(() => {
)}
<div className="mt-1.5">
{WORKSPACE_ACTION_LINKS.map((link) => (
<Link className="block w-full" key={link.key} href={link.href}>
<Link className="block w-full" key={link.key} href={link.href} onClick={handleItemClick}>
<Tooltip tooltipContent={link.label} position="right" className="ml-2" disabled={!sidebarCollapsed}>
<div
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium text-custom-sidebar-text-200 outline-none hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80 ${
sidebarCollapsed ? "justify-center" : ""
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium text-custom-sidebar-text-200 outline-none hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80 ${sidebarCollapsed ? "justify-center" : ""
}`}
>
{<link.Icon className="h-4 w-4" />}
@ -180,8 +208,7 @@ export const ProfileLayoutSidebar = observer(() => {
</div>
<div className="flex flex-shrink-0 flex-grow items-end px-6 py-2">
<div
className={`flex w-full ${
sidebarCollapsed ? "flex-col justify-center gap-2" : "items-center justify-between gap-2"
className={`flex w-full ${sidebarCollapsed ? "flex-col justify-center gap-2" : "items-center justify-between gap-2"
}`}
>
<button
@ -202,8 +229,7 @@ export const ProfileLayoutSidebar = observer(() => {
</button>
<button
type="button"
className={`ml-auto hidden place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 md:grid ${
sidebarCollapsed ? "w-full" : ""
className={`ml-auto hidden place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 md:grid ${sidebarCollapsed ? "w-full" : ""
}`}
onClick={() => toggleSidebar()}
>

View File

@ -28,9 +28,8 @@ export const ProfileAuthWrapper: React.FC<Props> = observer((props) => {
const isAuthorizedPath = router.pathname.includes("assigned" || "created" || "subscribed");
return (
<div className="h-full w-full md:flex md:flex-row-reverse md:overflow-hidden">
<ProfileSidebar />
<div className="flex w-full flex-col md:h-full md:overflow-hidden">
<div className="h-full w-full realtive flex flex-row">
<div className="w-full realtive flex flex-col">
<ProfileNavbar isAuthorized={isAuthorized} showProfileIssuesFilter={showProfileIssuesFilter} />
{isAuthorized || !isAuthorizedPath ? (
<div className={`w-full overflow-hidden md:h-full ${className}`}>{children}</div>
@ -40,6 +39,8 @@ export const ProfileAuthWrapper: React.FC<Props> = observer((props) => {
</div>
)}
</div>
<ProfileSidebar />
</div>
);
});

View File

@ -12,7 +12,7 @@ const ProfileAssignedIssuesPage: NextPageWithLayout = () => <ProfileIssuesPage t
ProfileAssignedIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<UserProfileHeader />}>
<AppLayout header={<UserProfileHeader type="Assigned" />}>
<ProfileAuthWrapper showProfileIssuesFilter>{page}</ProfileAuthWrapper>
</AppLayout>
);

View File

@ -14,7 +14,7 @@ const ProfileCreatedIssuesPage: NextPageWithLayout = () => <ProfileIssuesPage ty
ProfileCreatedIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<UserProfileHeader />}>
<AppLayout header={<UserProfileHeader type="Created" />}>
<ProfileAuthWrapper showProfileIssuesFilter>{page}</ProfileAuthWrapper>
</AppLayout>
);

View File

@ -56,7 +56,7 @@ const ProfileOverviewPage: NextPageWithLayout = () => {
ProfileOverviewPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<UserProfileHeader />}>
<AppLayout header={<UserProfileHeader type='Summary' />}>
<ProfileAuthWrapper>{page}</ProfileAuthWrapper>
</AppLayout>
);

View File

@ -14,7 +14,7 @@ const ProfileSubscribedIssuesPage: NextPageWithLayout = () => <ProfileIssuesPage
ProfileSubscribedIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<UserProfileHeader />}>
<AppLayout header={<UserProfileHeader type="Subscribed" />}>
<ProfileAuthWrapper showProfileIssuesFilter>{page}</ProfileAuthWrapper>
</AppLayout>
);

View File

@ -21,6 +21,7 @@ import { USER_ACTIVITY } from "constants/fetch-keys";
import { calculateTimeAgo } from "helpers/date-time.helper";
// type
import { NextPageWithLayout } from "lib/types";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
const userService = new UserService();
@ -30,8 +31,10 @@ const ProfileActivityPage: NextPageWithLayout = observer(() => {
const { currentUser } = useUser();
return (
<section className="mx-auto mt-16 flex h-full w-full flex-col overflow-hidden px-8 pb-8 lg:w-3/5">
<div className="flex items-center border-b border-custom-border-100 pb-3.5">
<section className="mx-auto mt-5 md:mt-16 flex h-full w-full flex-col overflow-hidden px-8 pb-8 lg:w-3/5">
<div className="flex items-center border-b border-custom-border-100 gap-4 pb-3.5">
<SidebarHamburgerToggle />
<h3 className="text-xl font-medium">Activity</h3>
</div>
{userActivity ? (
@ -187,6 +190,7 @@ const ProfileActivityPage: NextPageWithLayout = observer(() => {
</Loader>
)}
</section>
);
});

View File

@ -14,6 +14,7 @@ import { ProfileSettingsLayout } from "layouts/settings-layout";
import { Button, Input, Spinner } from "@plane/ui";
// types
import { NextPageWithLayout } from "lib/types";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
interface FormValues {
old_password: string;
@ -86,6 +87,10 @@ const ChangePasswordPage: NextPageWithLayout = observer(() => {
);
return (
<div className="flex flex-col h-full">
<div className="block md:hidden flex-shrink-0 border-b border-custom-border-200 p-4">
<SidebarHamburgerToggle />
</div>
<form
onSubmit={handleSubmit(handleChangePassword)}
className="mx-auto mt-16 flex h-full w-full flex-col gap-8 px-8 pb-8 lg:w-3/5"
@ -168,6 +173,7 @@ const ChangePasswordPage: NextPageWithLayout = observer(() => {
</Button>
</div>
</form>
</div>
);
});

View File

@ -23,6 +23,7 @@ import type { NextPageWithLayout } from "lib/types";
// constants
import { USER_ROLES } from "constants/workspace";
import { TIME_ZONES } from "constants/timezones";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
const defaultValues: Partial<IUser> = {
avatar: "",
@ -136,6 +137,11 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
return (
<>
<div className="flex flex-col h-full">
<div className="block md:hidden flex-shrink-0 border-b border-custom-border-200 p-4">
<SidebarHamburgerToggle />
</div>
<div className="overflow-hidden">
<Controller
control={control}
name="avatar"
@ -155,7 +161,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
)}
/>
<DeactivateAccountModal isOpen={deactivateAccountModal} onClose={() => setDeactivateAccountModal(false)} />
<div className="mx-auto flex h-full w-full flex-col space-y-10 overflow-y-auto pt-16 px-8 pb-8 lg:w-3/5">
<div className="mx-auto flex h-full w-full flex-col space-y-10 overflow-y-auto pt-10 md:pt-16 px-8 pb-8 lg:w-3/5">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="flex w-full flex-col gap-8">
<div className="relative h-44 w-full">
@ -289,8 +295,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
ref={ref}
hasError={Boolean(errors.email)}
placeholder="Enter your email"
className={`w-full rounded-md cursor-not-allowed !bg-custom-background-80 ${
errors.email ? "border-red-500" : ""
className={`w-full rounded-md cursor-not-allowed !bg-custom-background-80 ${errors.email ? "border-red-500" : ""
}`}
disabled
/>
@ -435,6 +440,8 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
)}
</Disclosure>
</div>
</div>
</div>
</>
);
});

View File

@ -48,7 +48,7 @@ const ProfilePreferencesThemePage: NextPageWithLayout = observer(() => {
return (
<>
{currentUser ? (
<div className="mx-auto mt-14 h-full w-full overflow-y-auto px-6 lg:px-20 pb-8">
<div className="mx-auto mt-10 md:mt-14 h-full w-full overflow-y-auto px-6 lg:px-20 pb-8">
<div className="flex items-center border-b border-custom-border-100 pb-3.5">
<h3 className="text-xl font-medium">Preferences</h3>
</div>

View File

@ -7,15 +7,18 @@ export interface IThemeStore {
// observables
theme: string | null;
sidebarCollapsed: boolean | undefined;
profileSidebarCollapsed: boolean | undefined;
// actions
toggleSidebar: (collapsed?: boolean) => void;
setTheme: (theme: any) => void;
toggleProfileSidebar: (collapsed?: boolean) => void;
}
export class ThemeStore implements IThemeStore {
// observables
sidebarCollapsed: boolean | undefined = undefined;
theme: string | null = null;
profileSidebarCollapsed: boolean | undefined = undefined;
// root store
rootStore;
@ -24,9 +27,11 @@ export class ThemeStore implements IThemeStore {
// observable
sidebarCollapsed: observable.ref,
theme: observable.ref,
profileSidebarCollapsed: observable.ref,
// action
toggleSidebar: action,
setTheme: action,
toggleProfileSidebar: action,
// computed
});
// root store
@ -46,6 +51,19 @@ export class ThemeStore implements IThemeStore {
localStorage.setItem("app_sidebar_collapsed", this.sidebarCollapsed.toString());
};
/**
* Toggle the profile sidebar collapsed state
* @param collapsed
*/
toggleProfileSidebar = (collapsed?: boolean) => {
if (collapsed === undefined) {
this.profileSidebarCollapsed = !this.profileSidebarCollapsed;
} else {
this.profileSidebarCollapsed = collapsed;
}
localStorage.setItem("profile_sidebar_collapsed", this.profileSidebarCollapsed.toString());
};
/**
* Sets the user theme and applies it to the platform
* @param _theme