fix: mobile responsive sidebar close on item tap (#3661)

This commit is contained in:
Ramesh Kumar Chandra 2024-02-14 14:55:33 +05:30 committed by GitHub
parent e51e4761b9
commit 1d2e331cec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 162 additions and 164 deletions

View File

@ -3,12 +3,20 @@ import { Menu } from "lucide-react";
import { useApplication } from "hooks/store"; import { useApplication } from "hooks/store";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
export const SidebarHamburgerToggle: FC = observer(() => { type Props = {
const { theme: themStore } = useApplication(); onClick?: () => void;
}
export const SidebarHamburgerToggle: FC<Props> = observer((props) => {
const { onClick } = props
const { theme: themeStore } = useApplication();
return ( return (
<div <div
className="w-7 h-7 flex-shrink-0 rounded flex justify-center items-center bg-custom-background-80 transition-all hover:bg-custom-background-90 cursor-pointer group md:hidden" className="w-7 h-7 flex-shrink-0 rounded flex justify-center items-center bg-custom-background-80 transition-all hover:bg-custom-background-90 cursor-pointer group md:hidden"
onClick={() => themStore.toggleMobileSidebar()} onClick={() => {
if (onClick) onClick()
else themeStore.toggleMobileSidebar()
}}
> >
<Menu size={14} className="text-custom-text-200 group-hover:text-custom-text-100 transition-all" /> <Menu size={14} className="text-custom-text-200 group-hover:text-custom-text-100 transition-all" />
</div> </div>

View File

@ -18,7 +18,7 @@ import {
MoreHorizontal, MoreHorizontal,
} from "lucide-react"; } from "lucide-react";
// hooks // hooks
import { useApplication,useEventTracker, useProject } from "hooks/store"; import { useApplication, useEventTracker, useProject } from "hooks/store";
import useOutsideClickDetector from "hooks/use-outside-click-detector"; import useOutsideClickDetector from "hooks/use-outside-click-detector";
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// helpers // helpers
@ -131,7 +131,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
const handleProjectClick = () => { const handleProjectClick = () => {
if (window.innerWidth < 768) { if (window.innerWidth < 768) {
themeStore.toggleSidebar(); themeStore.toggleMobileSidebar();
} }
}; };
@ -147,9 +147,8 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
{({ open }) => ( {({ open }) => (
<> <>
<div <div
className={`group relative flex w-full items-center rounded-md px-2 py-1 text-custom-sidebar-text-10 hover:bg-custom-sidebar-background-80 ${ className={`group relative flex w-full items-center rounded-md px-2 py-1 text-custom-sidebar-text-10 hover:bg-custom-sidebar-background-80 ${snapshot?.isDragging ? "opacity-60" : ""
snapshot?.isDragging ? "opacity-60" : "" } ${isMenuActive ? "!bg-custom-sidebar-background-80" : ""}`}
} ${isMenuActive ? "!bg-custom-sidebar-background-80" : ""}`}
> >
{provided && ( {provided && (
<Tooltip <Tooltip
@ -158,11 +157,9 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
> >
<button <button
type="button" type="button"
className={`absolute -left-2.5 top-1/2 hidden -translate-y-1/2 rounded p-0.5 text-custom-sidebar-text-400 ${ className={`absolute -left-2.5 top-1/2 hidden -translate-y-1/2 rounded p-0.5 text-custom-sidebar-text-400 ${isCollapsed ? "" : "group-hover:!flex"
isCollapsed ? "" : "group-hover:!flex" } ${project.sort_order === null ? "cursor-not-allowed opacity-60" : ""} ${isMenuActive ? "!flex" : ""
} ${project.sort_order === null ? "cursor-not-allowed opacity-60" : ""} ${ }`}
isMenuActive ? "!flex" : ""
}`}
{...provided?.dragHandleProps} {...provided?.dragHandleProps}
> >
<MoreVertical className="h-3.5" /> <MoreVertical className="h-3.5" />
@ -173,14 +170,12 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
<Tooltip tooltipContent={`${project.name}`} position="right" className="ml-2" disabled={!isCollapsed}> <Tooltip tooltipContent={`${project.name}`} position="right" className="ml-2" disabled={!isCollapsed}>
<Disclosure.Button <Disclosure.Button
as="div" as="div"
className={`flex flex-grow cursor-pointer select-none items-center truncate text-left text-sm font-medium ${ className={`flex flex-grow cursor-pointer select-none items-center truncate text-left text-sm font-medium ${isCollapsed ? "justify-center" : `justify-between`
isCollapsed ? "justify-center" : `justify-between` }`}
}`}
> >
<div <div
className={`flex w-full flex-grow items-center gap-x-2 truncate ${ className={`flex w-full flex-grow items-center gap-x-2 truncate ${isCollapsed ? "justify-center" : ""
isCollapsed ? "justify-center" : "" }`}
}`}
> >
{project.emoji ? ( {project.emoji ? (
<span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded uppercase"> <span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded uppercase">
@ -200,9 +195,8 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
</div> </div>
{!isCollapsed && ( {!isCollapsed && (
<ChevronDown <ChevronDown
className={`hidden h-4 w-4 flex-shrink-0 ${open ? "rotate-180" : ""} ${ className={`hidden h-4 w-4 flex-shrink-0 ${open ? "rotate-180" : ""} ${isMenuActive ? "!block" : ""
isMenuActive ? "!block" : "" } mb-0.5 text-custom-sidebar-text-400 duration-300 group-hover:!block`}
} mb-0.5 text-custom-sidebar-text-400 duration-300 group-hover:!block`}
/> />
)} )}
</Disclosure.Button> </Disclosure.Button>
@ -326,11 +320,10 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
disabled={!isCollapsed} disabled={!isCollapsed}
> >
<div <div
className={`group flex items-center gap-2.5 rounded-md px-2 py-1.5 text-xs font-medium outline-none ${ className={`group flex items-center gap-2.5 rounded-md px-2 py-1.5 text-xs font-medium outline-none ${router.asPath.includes(item.href)
router.asPath.includes(item.href) ? "bg-custom-primary-100/10 text-custom-primary-100"
? "bg-custom-primary-100/10 text-custom-primary-100" : "text-custom-sidebar-text-300 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
: "text-custom-sidebar-text-300 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80" } ${isCollapsed ? "justify-center" : ""}`}
} ${isCollapsed ? "justify-center" : ""}`}
> >
<item.Icon className="h-4 w-4 stroke-[1.5]" /> <item.Icon className="h-4 w-4 stroke-[1.5]" />
{!isCollapsed && item.name} {!isCollapsed && item.name}

View File

@ -10,6 +10,7 @@ import { FileText, HelpCircle, MessagesSquare, MoveLeft, Zap } from "lucide-reac
import { DiscordIcon, GithubIcon, Tooltip } from "@plane/ui"; import { DiscordIcon, GithubIcon, Tooltip } from "@plane/ui";
// assets // assets
import packageJson from "package.json"; import packageJson from "package.json";
import useSize from "hooks/use-window-size";
const helpOptions = [ const helpOptions = [
{ {
@ -42,9 +43,11 @@ export interface WorkspaceHelpSectionProps {
export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observer(() => { export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observer(() => {
// store hooks // store hooks
const { const {
theme: { sidebarCollapsed, toggleSidebar }, theme: { sidebarCollapsed, toggleSidebar, toggleMobileSidebar },
commandPalette: { toggleShortcutModal }, commandPalette: { toggleShortcutModal },
} = useApplication(); } = useApplication();
const [windowWidth] = useSize();
// states // states
const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false); const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false);
// refs // refs
@ -57,9 +60,8 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
return ( return (
<> <>
<div <div
className={`flex w-full items-center justify-between gap-1 self-baseline border-t border-custom-border-200 bg-custom-sidebar-background-100 px-4 py-2 ${ className={`flex w-full items-center justify-between gap-1 self-baseline border-t border-custom-border-200 bg-custom-sidebar-background-100 px-4 py-2 ${isCollapsed ? "flex-col" : ""
isCollapsed ? "flex-col" : "" }`}
}`}
> >
{!isCollapsed && ( {!isCollapsed && (
<div className="w-1/2 cursor-default rounded-md bg-green-500/10 px-2.5 py-1.5 text-center text-sm font-medium text-green-500 outline-none"> <div className="w-1/2 cursor-default rounded-md bg-green-500/10 px-2.5 py-1.5 text-center text-sm font-medium text-green-500 outline-none">
@ -70,9 +72,8 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
<Tooltip tooltipContent="Shortcuts"> <Tooltip tooltipContent="Shortcuts">
<button <button
type="button" type="button"
className={`grid place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 ${ className={`grid place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 ${isCollapsed ? "w-full" : ""
isCollapsed ? "w-full" : "" }`}
}`}
onClick={() => toggleShortcutModal(true)} onClick={() => toggleShortcutModal(true)}
> >
<Zap className="h-3.5 w-3.5" /> <Zap className="h-3.5 w-3.5" />
@ -81,9 +82,8 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
<Tooltip tooltipContent="Help"> <Tooltip tooltipContent="Help">
<button <button
type="button" type="button"
className={`grid place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 ${ className={`grid place-items-center rounded-md p-1.5 text-custom-text-200 outline-none hover:bg-custom-background-90 hover:text-custom-text-100 ${isCollapsed ? "w-full" : ""
isCollapsed ? "w-full" : "" }`}
}`}
onClick={() => setIsNeedHelpOpen((prev) => !prev)} onClick={() => setIsNeedHelpOpen((prev) => !prev)}
> >
<HelpCircle className="h-3.5 w-3.5" /> <HelpCircle className="h-3.5 w-3.5" />
@ -93,7 +93,7 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
<button <button
type="button" type="button"
className="grid 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:hidden" className="grid 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:hidden"
onClick={() => toggleSidebar()} onClick={() => windowWidth <= 768 ? toggleMobileSidebar() : toggleSidebar()}
> >
<MoveLeft className="h-3.5 w-3.5" /> <MoveLeft className="h-3.5 w-3.5" />
</button> </button>
@ -101,10 +101,9 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
<Tooltip tooltipContent={`${isCollapsed ? "Expand" : "Hide"}`}> <Tooltip tooltipContent={`${isCollapsed ? "Expand" : "Hide"}`}>
<button <button
type="button" type="button"
className={`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 ${ className={`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 ${isCollapsed ? "w-full" : ""
isCollapsed ? "w-full" : "" }`}
}`} onClick={() => windowWidth <= 768 ? toggleMobileSidebar() : toggleSidebar()}
onClick={() => toggleSidebar()}
> >
<MoveLeft className={`h-3.5 w-3.5 duration-300 ${isCollapsed ? "rotate-180" : ""}`} /> <MoveLeft className={`h-3.5 w-3.5 duration-300 ${isCollapsed ? "rotate-180" : ""}`} />
</button> </button>
@ -122,9 +121,8 @@ export const WorkspaceHelpSection: React.FC<WorkspaceHelpSectionProps> = observe
leaveTo="transform opacity-0 scale-95" leaveTo="transform opacity-0 scale-95"
> >
<div <div
className={`absolute bottom-2 min-w-[10rem] ${ className={`absolute bottom-2 min-w-[10rem] ${isCollapsed ? "left-full" : "-left-[75px]"
isCollapsed ? "left-full" : "-left-[75px]" } divide-y divide-custom-border-200 whitespace-nowrap rounded bg-custom-background-100 p-1 shadow-custom-shadow-xs`}
} divide-y divide-custom-border-200 whitespace-nowrap rounded bg-custom-background-100 p-1 shadow-custom-shadow-xs`}
ref={helpOptionsRef} ref={helpOptionsRef}
> >
<div className="space-y-1 pb-2"> <div className="space-y-1 pb-2">

View File

@ -54,7 +54,7 @@ export const WorkspaceSidebarDropdown = observer(() => {
const { workspaceSlug } = router.query; const { workspaceSlug } = router.query;
// store hooks // store hooks
const { const {
theme: { sidebarCollapsed, toggleSidebar }, theme: { sidebarCollapsed, toggleMobileSidebar },
} = useApplication(); } = useApplication();
const { setTrackElement } = useEventTracker(); const { setTrackElement } = useEventTracker();
const { currentUser, updateCurrentUser, isUserInstanceAdmin, signOut } = useUser(); const { currentUser, updateCurrentUser, isUserInstanceAdmin, signOut } = useUser();
@ -98,7 +98,7 @@ export const WorkspaceSidebarDropdown = observer(() => {
}; };
const handleItemClick = () => { const handleItemClick = () => {
if (window.innerWidth < 768) { if (window.innerWidth < 768) {
toggleSidebar(); toggleMobileSidebar();
} }
}; };
const workspacesList = Object.values(workspaces ?? {}); const workspacesList = Object.values(workspaces ?? {});
@ -110,15 +110,13 @@ export const WorkspaceSidebarDropdown = observer(() => {
<> <>
<Menu.Button className="group/menu-button h-full w-full truncate rounded-md text-sm font-medium text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:outline-none"> <Menu.Button className="group/menu-button h-full w-full truncate rounded-md text-sm font-medium text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:outline-none">
<div <div
className={`flex items-center gap-x-2 truncate rounded p-1 ${ className={`flex items-center gap-x-2 truncate rounded p-1 ${sidebarCollapsed ? "justify-center" : "justify-between"
sidebarCollapsed ? "justify-center" : "justify-between" }`}
}`}
> >
<div className="flex items-center gap-2 truncate"> <div className="flex items-center gap-2 truncate">
<div <div
className={`relative grid h-6 w-6 flex-shrink-0 place-items-center uppercase ${ className={`relative grid h-6 w-6 flex-shrink-0 place-items-center uppercase ${!activeWorkspace?.logo && "rounded bg-custom-primary-500 text-white"
!activeWorkspace?.logo && "rounded bg-custom-primary-500 text-white" }`}
}`}
> >
{activeWorkspace?.logo && activeWorkspace.logo !== "" ? ( {activeWorkspace?.logo && activeWorkspace.logo !== "" ? (
<img <img
@ -138,9 +136,8 @@ export const WorkspaceSidebarDropdown = observer(() => {
</div> </div>
{!sidebarCollapsed && ( {!sidebarCollapsed && (
<ChevronDown <ChevronDown
className={`mx-1 hidden h-4 w-4 flex-shrink-0 group-hover/menu-button:block ${ className={`mx-1 hidden h-4 w-4 flex-shrink-0 group-hover/menu-button:block ${open ? "rotate-180" : ""
open ? "rotate-180" : "" } text-custom-sidebar-text-400 duration-300`}
} text-custom-sidebar-text-400 duration-300`}
/> />
)} )}
</div> </div>
@ -179,9 +176,8 @@ export const WorkspaceSidebarDropdown = observer(() => {
> >
<div className="flex items-center justify-start gap-2.5 truncate"> <div className="flex items-center justify-start gap-2.5 truncate">
<span <span
className={`relative flex h-6 w-6 flex-shrink-0 items-center justify-center p-2 text-xs uppercase ${ 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 && "rounded bg-custom-primary-500 text-white" }`}
}`}
> >
{workspace?.logo && workspace.logo !== "" ? ( {workspace?.logo && workspace.logo !== "" ? (
<img <img
@ -194,9 +190,8 @@ export const WorkspaceSidebarDropdown = observer(() => {
)} )}
</span> </span>
<h5 <h5
className={`truncate text-sm font-medium ${ className={`truncate text-sm font-medium ${workspaceSlug === workspace.slug ? "" : "text-custom-text-200"
workspaceSlug === workspace.slug ? "" : "text-custom-text-200" }`}
}`}
> >
{workspace.name} {workspace.name}
</h5> </h5>

View File

@ -31,7 +31,7 @@ export const WorkspaceSidebarMenu = observer(() => {
const handleLinkClick = (itemKey: string) => { const handleLinkClick = (itemKey: string) => {
if (window.innerWidth < 768) { if (window.innerWidth < 768) {
themeStore.toggleSidebar(); themeStore.toggleMobileSidebar();
} }
captureEvent(SIDEBAR_CLICKED, { captureEvent(SIDEBAR_CLICKED, {
destination: itemKey, destination: itemKey,
@ -52,11 +52,10 @@ export const WorkspaceSidebarMenu = observer(() => {
disabled={!themeStore?.sidebarCollapsed} disabled={!themeStore?.sidebarCollapsed}
> >
<div <div
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium outline-none ${ 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.asPath, `/${workspaceSlug}`)
link.highlight(router.asPath, `/${workspaceSlug}`) ? "bg-custom-primary-100/10 text-custom-primary-100"
? "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"
: "text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80" } ${themeStore?.sidebarCollapsed ? "justify-center" : ""}`}
} ${themeStore?.sidebarCollapsed ? "justify-center" : ""}`}
> >
{ {
<link.Icon <link.Icon

View File

@ -7,6 +7,7 @@ import { CustomMenu } from "@plane/ui";
import { ChevronDown } from "lucide-react"; import { ChevronDown } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useApplication } from "hooks/store";
interface IProfilePreferenceSettingsLayout { interface IProfilePreferenceSettingsLayout {
children: ReactNode; children: ReactNode;
@ -16,6 +17,7 @@ interface IProfilePreferenceSettingsLayout {
export const ProfilePreferenceSettingsLayout: FC<IProfilePreferenceSettingsLayout> = (props) => { export const ProfilePreferenceSettingsLayout: FC<IProfilePreferenceSettingsLayout> = (props) => {
const { children, header } = props; const { children, header } = props;
const router = useRouter(); const router = useRouter();
const { theme: themeStore } = useApplication();
const showMenuItem = () => { const showMenuItem = () => {
const item = router.asPath.split('/'); const item = router.asPath.split('/');
@ -42,7 +44,7 @@ export const ProfilePreferenceSettingsLayout: FC<IProfilePreferenceSettingsLayou
return ( return (
<ProfileSettingsLayout header={ <ProfileSettingsLayout header={
<div className="md:hidden flex flex-shrink-0 gap-4 items-center justify-start border-b border-custom-border-200 p-4"> <div className="md:hidden flex flex-shrink-0 gap-4 items-center justify-start border-b border-custom-border-200 p-4">
<SidebarHamburgerToggle /> <SidebarHamburgerToggle onClick={() => themeStore.toggleSidebar()} />
<CustomMenu <CustomMenu
maxHeight={"md"} maxHeight={"md"}
className="flex flex-grow justify-center text-custom-text-200 text-sm" className="flex flex-grow justify-center text-custom-text-200 text-sm"

View File

@ -40,7 +40,7 @@ export const ProfileLayoutSidebar = observer(() => {
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
// store hooks // store hooks
const { const {
theme: { sidebarCollapsed, toggleSidebar }, theme: { sidebarCollapsed, toggleSidebar, toggleMobileSidebar },
} = useApplication(); } = useApplication();
const { currentUser, currentUserSettings, signOut } = useUser(); const { currentUser, currentUserSettings, signOut } = useUser();
const { workspaces } = useWorkspace(); const { workspaces } = useWorkspace();
@ -78,7 +78,7 @@ export const ProfileLayoutSidebar = observer(() => {
const handleItemClick = () => { const handleItemClick = () => {
if (window.innerWidth < 768) { if (window.innerWidth < 768) {
toggleSidebar(); toggleMobileSidebar();
} }
}; };
@ -111,7 +111,7 @@ export const ProfileLayoutSidebar = observer(() => {
`} `}
> >
<div ref={ref} 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}`}> <Link href={`/${redirectWorkspaceSlug}`} onClick={handleItemClick}>
<div <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" : ""
}`} }`}

View File

@ -3,7 +3,7 @@ import useSWR from "swr";
import Link from "next/link"; import Link from "next/link";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
//hooks //hooks
import { useUser } from "hooks/store"; import { useApplication, useUser } from "hooks/store";
// services // services
import { UserService } from "services/user.service"; import { UserService } from "services/user.service";
// layouts // layouts
@ -29,11 +29,12 @@ const ProfileActivityPage: NextPageWithLayout = observer(() => {
const { data: userActivity } = useSWR(USER_ACTIVITY, () => userService.getUserActivity()); const { data: userActivity } = useSWR(USER_ACTIVITY, () => userService.getUserActivity());
// store hooks // store hooks
const { currentUser } = useUser(); const { currentUser } = useUser();
const { theme: themeStore } = useApplication();
return ( return (
<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"> <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"> <div className="flex items-center border-b border-custom-border-100 gap-4 pb-3.5">
<SidebarHamburgerToggle /> <SidebarHamburgerToggle onClick={() => themeStore.toggleSidebar()} />
<h3 className="text-xl font-medium">Activity</h3> <h3 className="text-xl font-medium">Activity</h3>
</div> </div>
{userActivity ? ( {userActivity ? (
@ -96,12 +97,12 @@ const ProfileActivityPage: NextPageWithLayout = observer(() => {
const message = const message =
activityItem.verb === "created" && activityItem.verb === "created" &&
activityItem.field !== "cycles" && activityItem.field !== "cycles" &&
activityItem.field !== "modules" && activityItem.field !== "modules" &&
activityItem.field !== "attachment" && activityItem.field !== "attachment" &&
activityItem.field !== "link" && activityItem.field !== "link" &&
activityItem.field !== "estimate" && activityItem.field !== "estimate" &&
!activityItem.field ? ( !activityItem.field ? (
<span> <span>
created <IssueLink activity={activityItem} /> created <IssueLink activity={activityItem} />
</span> </span>

View File

@ -3,7 +3,7 @@ import { useRouter } from "next/router";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
// hooks // hooks
import { useUser } from "hooks/store"; import { useApplication, useUser } from "hooks/store";
// services // services
import { UserService } from "services/user.service"; import { UserService } from "services/user.service";
// hooks // hooks
@ -32,7 +32,8 @@ const userService = new UserService();
const ChangePasswordPage: NextPageWithLayout = observer(() => { const ChangePasswordPage: NextPageWithLayout = observer(() => {
const [isPageLoading, setIsPageLoading] = useState(true); const [isPageLoading, setIsPageLoading] = useState(true);
// hooks
const { theme: themeStore } = useApplication();
const { currentUser } = useUser(); const { currentUser } = useUser();
const router = useRouter(); const router = useRouter();
@ -89,90 +90,90 @@ const ChangePasswordPage: NextPageWithLayout = observer(() => {
return ( return (
<div className="flex flex-col h-full"> <div className="flex flex-col h-full">
<div className="block md:hidden flex-shrink-0 border-b border-custom-border-200 p-4"> <div className="block md:hidden flex-shrink-0 border-b border-custom-border-200 p-4">
<SidebarHamburgerToggle /> <SidebarHamburgerToggle onClick={() => themeStore.toggleSidebar()} />
</div> </div>
<form <form
onSubmit={handleSubmit(handleChangePassword)} 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" className="mx-auto mt-16 flex h-full w-full flex-col gap-8 px-8 pb-8 lg:w-3/5"
> >
<h3 className="text-xl font-medium">Change password</h3> <h3 className="text-xl font-medium">Change password</h3>
<div className="grid-col grid w-full grid-cols-1 items-center justify-between gap-10 xl:grid-cols-2 2xl:grid-cols-3"> <div className="grid-col grid w-full grid-cols-1 items-center justify-between gap-10 xl:grid-cols-2 2xl:grid-cols-3">
<div className="flex flex-col gap-1 "> <div className="flex flex-col gap-1 ">
<h4 className="text-sm">Current password</h4> <h4 className="text-sm">Current password</h4>
<Controller <Controller
control={control} control={control}
name="old_password" name="old_password"
rules={{ rules={{
required: "This field is required", required: "This field is required",
}} }}
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => (
<Input <Input
id="old_password" id="old_password"
type="password" type="password"
value={value} value={value}
onChange={onChange} onChange={onChange}
placeholder="Old password" placeholder="Old password"
className="w-full rounded-md font-medium" className="w-full rounded-md font-medium"
hasError={Boolean(errors.old_password)} hasError={Boolean(errors.old_password)}
/> />
)} )}
/> />
{errors.old_password && <span className="text-xs text-red-500">{errors.old_password.message}</span>} {errors.old_password && <span className="text-xs text-red-500">{errors.old_password.message}</span>}
</div>
<div className="flex flex-col gap-1 ">
<h4 className="text-sm">New password</h4>
<Controller
control={control}
name="new_password"
rules={{
required: "This field is required",
}}
render={({ field: { value, onChange } }) => (
<Input
id="new_password"
type="password"
value={value}
placeholder="New password"
onChange={onChange}
className="w-full"
hasError={Boolean(errors.new_password)}
/>
)}
/>
{errors.new_password && <span className="text-xs text-red-500">{errors.new_password.message}</span>}
</div>
<div className="flex flex-col gap-1 ">
<h4 className="text-sm">Confirm password</h4>
<Controller
control={control}
name="confirm_password"
rules={{
required: "This field is required",
}}
render={({ field: { value, onChange } }) => (
<Input
id="confirm_password"
type="password"
placeholder="Confirm password"
value={value}
onChange={onChange}
className="w-full"
hasError={Boolean(errors.confirm_password)}
/>
)}
/>
{errors.confirm_password && <span className="text-xs text-red-500">{errors.confirm_password.message}</span>}
</div>
</div> </div>
<div className="flex flex-col gap-1 "> <div className="flex items-center justify-between py-2">
<h4 className="text-sm">New password</h4> <Button variant="primary" type="submit" loading={isSubmitting}>
<Controller {isSubmitting ? "Changing password..." : "Change password"}
control={control} </Button>
name="new_password"
rules={{
required: "This field is required",
}}
render={({ field: { value, onChange } }) => (
<Input
id="new_password"
type="password"
value={value}
placeholder="New password"
onChange={onChange}
className="w-full"
hasError={Boolean(errors.new_password)}
/>
)}
/>
{errors.new_password && <span className="text-xs text-red-500">{errors.new_password.message}</span>}
</div> </div>
</form>
<div className="flex flex-col gap-1 ">
<h4 className="text-sm">Confirm password</h4>
<Controller
control={control}
name="confirm_password"
rules={{
required: "This field is required",
}}
render={({ field: { value, onChange } }) => (
<Input
id="confirm_password"
type="password"
placeholder="Confirm password"
value={value}
onChange={onChange}
className="w-full"
hasError={Boolean(errors.confirm_password)}
/>
)}
/>
{errors.confirm_password && <span className="text-xs text-red-500">{errors.confirm_password.message}</span>}
</div>
</div>
<div className="flex items-center justify-between py-2">
<Button variant="primary" type="submit" loading={isSubmitting}>
{isSubmitting ? "Changing password..." : "Change password"}
</Button>
</div>
</form>
</div> </div>
); );
}); });

View File

@ -5,7 +5,7 @@ import { observer } from "mobx-react-lite";
// services // services
import { FileService } from "services/file.service"; import { FileService } from "services/file.service";
// hooks // hooks
import { useUser } from "hooks/store"; import { useApplication, useUser } from "hooks/store";
import useUserAuth from "hooks/use-user-auth"; import useUserAuth from "hooks/use-user-auth";
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
// layouts // layouts
@ -58,6 +58,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
const { currentUser: myProfile, updateCurrentUser, currentUserLoader } = useUser(); const { currentUser: myProfile, updateCurrentUser, currentUserLoader } = useUser();
// custom hooks // custom hooks
const { } = useUserAuth({ user: myProfile, isLoading: currentUserLoader }); const { } = useUserAuth({ user: myProfile, isLoading: currentUserLoader });
const { theme: themeStore } = useApplication();
useEffect(() => { useEffect(() => {
reset({ ...defaultValues, ...myProfile }); reset({ ...defaultValues, ...myProfile });
@ -139,7 +140,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
<> <>
<div className="flex flex-col h-full"> <div className="flex flex-col h-full">
<div className="block md:hidden flex-shrink-0 border-b border-custom-border-200 p-4"> <div className="block md:hidden flex-shrink-0 border-b border-custom-border-200 p-4">
<SidebarHamburgerToggle /> <SidebarHamburgerToggle onClick={() => themeStore.toggleSidebar()} />
</div> </div>
<div className="overflow-hidden"> <div className="overflow-hidden">
<Controller <Controller