diff --git a/web/components/profile/preferences/preferences-mobile-header.tsx b/web/components/profile/preferences/preferences-mobile-header.tsx
new file mode 100644
index 000000000..41ad464ae
--- /dev/null
+++ b/web/components/profile/preferences/preferences-mobile-header.tsx
@@ -0,0 +1,38 @@
+import Link from "next/link";
+import router from "next/router";
+// helpers
+import { cn } from "@/helpers/common.helper";
+
+export const PreferencesMobileHeader = () => {
+ const profilePreferenceLinks: Array<{
+ label: string;
+ href: string;
+ }> = [
+ {
+ label: "Theme",
+ href: `/profile/preferences/theme`,
+ },
+ {
+ label: "Email",
+ href: `/profile/preferences/email`,
+ },
+ ];
+
+ return (
+
+ {profilePreferenceLinks.map((link, index) => (
+
console.log(router.asPath)}
+ className={cn(
+ "flex justify-around py-2 w-full",
+ router.asPath.includes(link.label.toLowerCase()) ? "border-b-2 border-custom-primary-100" : ""
+ )}
+ >
+
{link.label}
+
+ ))}
+
+ );
+};
diff --git a/web/components/profile/profile-issues-mobile-header.tsx b/web/components/profile/profile-issues-mobile-header.tsx
new file mode 100644
index 000000000..6880f6b4b
--- /dev/null
+++ b/web/components/profile/profile-issues-mobile-header.tsx
@@ -0,0 +1,177 @@
+import { useCallback } from "react";
+import { observer } from "mobx-react";
+import { useRouter } from "next/router";
+// icons
+import { ChevronDown } from "lucide-react";
+// types
+import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "@plane/types";
+// ui
+import { CustomMenu } from "@plane/ui";
+// components
+import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "@/components/issues";
+// constants
+import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT, ISSUE_LAYOUTS } from "@/constants/issue";
+// hooks
+import { useIssues, useLabel } from "@/hooks/store";
+
+
+const ProfileIssuesMobileHeader = observer(() => {
+ // router
+ const router = useRouter();
+ const { workspaceSlug, userId } = router.query;
+ // store hook
+ const {
+ issuesFilter: { issueFilters, updateFilters },
+ } = useIssues(EIssuesStoreType.PROFILE);
+
+ const { workspaceLabels } = useLabel();
+ // derived values
+ const states = undefined;
+ // const members = undefined;
+ // const activeLayout = issueFilters?.displayFilters?.layout;
+ // const states = undefined;
+ const members = undefined;
+ const activeLayout = issueFilters?.displayFilters?.layout;
+
+ const handleLayoutChange = useCallback(
+ (layout: TIssueLayouts) => {
+ if (!workspaceSlug || !userId) return;
+ updateFilters(
+ workspaceSlug.toString(),
+ undefined,
+ EIssueFilterType.DISPLAY_FILTERS,
+ { layout: layout },
+ userId.toString()
+ );
+ },
+ [workspaceSlug, updateFilters, userId]
+ );
+
+ const handleFiltersUpdate = useCallback(
+ (key: keyof IIssueFilterOptions, value: string | string[]) => {
+ if (!workspaceSlug || !userId) return;
+ const newValues = issueFilters?.filters?.[key] ?? [];
+
+ if (Array.isArray(value)) {
+ value.forEach((val) => {
+ if (!newValues.includes(val)) newValues.push(val);
+ });
+ } else {
+ if (issueFilters?.filters?.[key]?.includes(value)) newValues.splice(newValues.indexOf(value), 1);
+ else newValues.push(value);
+ }
+
+ updateFilters(
+ workspaceSlug.toString(),
+ undefined,
+ EIssueFilterType.FILTERS,
+ { [key]: newValues },
+ userId.toString()
+ );
+ },
+ [workspaceSlug, issueFilters, updateFilters, userId]
+ );
+
+ const handleDisplayFilters = useCallback(
+ (updatedDisplayFilter: Partial) => {
+ if (!workspaceSlug || !userId) return;
+ updateFilters(
+ workspaceSlug.toString(),
+ undefined,
+ EIssueFilterType.DISPLAY_FILTERS,
+ updatedDisplayFilter,
+ userId.toString()
+ );
+ },
+ [workspaceSlug, updateFilters, userId]
+ );
+
+ const handleDisplayProperties = useCallback(
+ (property: Partial) => {
+ if (!workspaceSlug || !userId) return;
+ updateFilters(
+ workspaceSlug.toString(),
+ undefined,
+ EIssueFilterType.DISPLAY_PROPERTIES,
+ property,
+ userId.toString()
+ );
+ },
+ [workspaceSlug, updateFilters, userId]
+ );
+ return (
+
+
Layout}
+ customButtonClassName="flex flex-grow justify-center text-custom-text-200 text-sm"
+ closeOnSelect
+ >
+ {ISSUE_LAYOUTS.map((layout, index) => {
+ if (layout.key === "spreadsheet" || layout.key === "gantt_chart" || layout.key === "calendar") return;
+ return (
+ {
+ handleLayoutChange(ISSUE_LAYOUTS[index].key);
+ }}
+ className="flex items-center gap-2"
+ >
+
+ {layout.title}
+
+ );
+ })}
+
+
+
+ Filters
+
+
+ }
+ >
+
+
+
+
+
+ Display
+
+
+ }
+ >
+
+
+
+
+ );
+});
+
+export default ProfileIssuesMobileHeader;
diff --git a/web/layouts/settings-layout/profile/preferences/layout.tsx b/web/layouts/settings-layout/profile/preferences/layout.tsx
index f7fff2ef1..4219696e2 100644
--- a/web/layouts/settings-layout/profile/preferences/layout.tsx
+++ b/web/layouts/settings-layout/profile/preferences/layout.tsx
@@ -1,10 +1,7 @@
import { FC, ReactNode } from "react";
// layout
-import Link from "next/link";
-import { useRouter } from "next/router";
-import { ChevronDown } from "lucide-react";
-import { CustomMenu } from "@plane/ui";
import { SidebarHamburgerToggle } from "@/components/core/sidebar/sidebar-menu-hamburger-toggle";
+import { PreferencesMobileHeader } from "@/components/profile/preferences/preferences-mobile-header";
import { useApplication } from "@/hooks/store";
import { ProfileSettingsLayout } from "@/layouts/settings-layout";
import { ProfilePreferenceSettingsSidebar } from "./sidebar";
@@ -16,65 +13,26 @@ interface IProfilePreferenceSettingsLayout {
export const ProfilePreferenceSettingsLayout: FC = (props) => {
const { children, header } = props;
- const router = useRouter();
const { theme: themeStore } = useApplication();
- const showMenuItem = () => {
- const item = router.asPath.split("/");
- let splittedItem = item[item.length - 1];
- splittedItem = splittedItem.replace(splittedItem[0], splittedItem[0].toUpperCase());
- return splittedItem;
- };
-
- const profilePreferenceLinks: Array<{
- label: string;
- href: string;
- }> = [
- {
- label: "Theme",
- href: `/profile/preferences/theme`,
- },
- {
- label: "Email",
- href: `/profile/preferences/email`,
- },
- ];
return (
themeStore.toggleSidebar()} />
-
- {showMenuItem()}
-
-
- }
- customButtonClassName="flex flex-grow justify-start text-custom-text-200 text-sm"
- >
- <>>
- {profilePreferenceLinks.map((link) => (
-
-
- {link.label}
-
-
- ))}
-
}
>
-
-
-
- {header}
- {children}
-
+
+
+
+
+
+ {header}
+ {children}
+
+
);
diff --git a/web/layouts/user-profile-layout/layout.tsx b/web/layouts/user-profile-layout/layout.tsx
index ba7a3a88e..4f173353a 100644
--- a/web/layouts/user-profile-layout/layout.tsx
+++ b/web/layouts/user-profile-layout/layout.tsx
@@ -2,10 +2,10 @@ import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
// components
import { ProfileNavbar, ProfileSidebar } from "@/components/profile";
-// hooks
-import { useUser } from "@/hooks/store";
// constants
import { EUserWorkspaceRoles } from "@/constants/workspace";
+// hooks
+import { useUser } from "@/hooks/store";
type Props = {
children: React.ReactNode;
@@ -28,8 +28,7 @@ export const ProfileAuthWrapper: React.FC
= observer((props) => {
const isAuthorizedPath = router.pathname.includes("assigned" || "created" || "subscribed");
return (
-
-
+
{isAuthorized || !isAuthorizedPath ? (
@@ -40,6 +39,7 @@ export const ProfileAuthWrapper: React.FC
= observer((props) => {
)}
+
);
});
diff --git a/web/pages/[workspaceSlug]/profile/[userId]/assigned.tsx b/web/pages/[workspaceSlug]/profile/[userId]/assigned.tsx
index bc770cc95..2d73195fe 100644
--- a/web/pages/[workspaceSlug]/profile/[userId]/assigned.tsx
+++ b/web/pages/[workspaceSlug]/profile/[userId]/assigned.tsx
@@ -1,11 +1,12 @@
import React, { ReactElement } from "react";
-// layouts
+// components
import { PageHead } from "@/components/core";
import { UserProfileHeader } from "@/components/headers";
import { ProfileIssuesPage } from "@/components/profile/profile-issues";
+import ProfileIssuesMobileHeader from "@/components/profile/profile-issues-mobile-header";
+// layouts
import { AppLayout } from "@/layouts/app-layout";
import { ProfileAuthWrapper } from "@/layouts/user-profile-layout";
-// components
// types
import { NextPageWithLayout } from "@/lib/types";
@@ -18,7 +19,7 @@ const ProfileAssignedIssuesPage: NextPageWithLayout = () => (
ProfileAssignedIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
- }>
+ } mobileHeader={}>
{page}
);
diff --git a/web/pages/[workspaceSlug]/profile/[userId]/created.tsx b/web/pages/[workspaceSlug]/profile/[userId]/created.tsx
index ef7179f0b..169ab4841 100644
--- a/web/pages/[workspaceSlug]/profile/[userId]/created.tsx
+++ b/web/pages/[workspaceSlug]/profile/[userId]/created.tsx
@@ -1,13 +1,14 @@
import { ReactElement } from "react";
// store
import { observer } from "mobx-react-lite";
-// layouts
+// components
import { PageHead } from "@/components/core";
import { UserProfileHeader } from "@/components/headers";
import { ProfileIssuesPage } from "@/components/profile/profile-issues";
+import ProfileIssuesMobileHeader from "@/components/profile/profile-issues-mobile-header";
+// layouts
import { AppLayout } from "@/layouts/app-layout";
import { ProfileAuthWrapper } from "@/layouts/user-profile-layout";
-// components
// types
import { NextPageWithLayout } from "@/lib/types";
@@ -20,7 +21,7 @@ const ProfileCreatedIssuesPage: NextPageWithLayout = () => (
ProfileCreatedIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
- }>
+ } mobileHeader={}>
{page}
);
diff --git a/web/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx b/web/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx
index e4a871ec8..feb7a0160 100644
--- a/web/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx
+++ b/web/pages/[workspaceSlug]/profile/[userId]/subscribed.tsx
@@ -1,13 +1,14 @@
import { ReactElement } from "react";
// store
import { observer } from "mobx-react-lite";
-// layouts
+// components
import { PageHead } from "@/components/core";
import { UserProfileHeader } from "@/components/headers";
import { ProfileIssuesPage } from "@/components/profile/profile-issues";
+import ProfileIssuesMobileHeader from "@/components/profile/profile-issues-mobile-header";
+// layouts
import { AppLayout } from "@/layouts/app-layout";
import { ProfileAuthWrapper } from "@/layouts/user-profile-layout";
-// components
// types
import { NextPageWithLayout } from "@/lib/types";
@@ -20,7 +21,7 @@ const ProfileSubscribedIssuesPage: NextPageWithLayout = () => (
ProfileSubscribedIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
- }>
+ } mobileHeader={}>
{page}
);
diff --git a/web/pages/profile/change-password.tsx b/web/pages/profile/change-password.tsx
index 01bedb83d..6e496862d 100644
--- a/web/pages/profile/change-password.tsx
+++ b/web/pages/profile/change-password.tsx
@@ -91,7 +91,7 @@ const ChangePasswordPage: NextPageWithLayout = observer(() => {