Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import HeaderUserProxyDropdown from "@/components/header/user/proxy/HeaderUserProxyDropdown";
import HeaderUserMenuDropdown from "@/components/header/user/HeaderUserMenuDropdown";
import { AuthContext } from "@/components/auth/Auth";

jest.mock(
"@/components/header/user/proxy/HeaderUserProxyDropdownItem",
() => () => <div data-testid="item" />
);
jest.mock("@/components/header/user/HeaderUserProxyDropdownItem", () => () => (
<div data-testid="item" />
));
jest.mock(
"@/components/header/user/connected/HeaderUserConnectedAccounts",
() => (props: any) => (
Expand Down Expand Up @@ -62,7 +61,7 @@ function renderDropdown(options: any) {
const onClose = jest.fn();
render(
<AuthContext.Provider value={authValue}>
<HeaderUserProxyDropdown
<HeaderUserMenuDropdown
isOpen
profile={options.profile}
onClose={onClose}
Expand All @@ -74,7 +73,7 @@ function renderDropdown(options: any) {

afterEach(() => jest.clearAllMocks());

describe("HeaderUserProxyDropdown", () => {
describe("HeaderUserMenuDropdown", () => {
it("shows profile handle as label", () => {
renderDropdown({
profile: profileBase,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import HeaderUserProxyDropdownItem from '@/components/header/user/proxy/HeaderUserProxyDropdownItem';
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import HeaderUserProxyDropdownItem from "@/components/header/user/HeaderUserProxyDropdownItem";

const profile = {
id: 1,
created_by: { handle: 'alice', pfp: 'img.png' }
created_by: { handle: "alice", pfp: "img.png" },
};

describe('HeaderUserProxyDropdownItem', () => {
it('activates proxy when not active', async () => {
describe("HeaderUserProxyDropdownItem", () => {
it("activates proxy when not active", async () => {
const activate = jest.fn();
render(
<HeaderUserProxyDropdownItem
Expand All @@ -17,13 +17,13 @@ describe('HeaderUserProxyDropdownItem', () => {
onActivateProfileProxy={activate}
/>
);
const btn = screen.getByRole('button');
const btn = screen.getByRole("button");
await userEvent.click(btn);
expect(activate).toHaveBeenCalledWith(profile);
expect(screen.getByText('alice')).toBeInTheDocument();
expect(screen.getByText("alice")).toBeInTheDocument();
});

it('deactivates proxy when active', async () => {
it("deactivates proxy when active", async () => {
const activate = jest.fn();
render(
<HeaderUserProxyDropdownItem
Expand All @@ -32,9 +32,9 @@ describe('HeaderUserProxyDropdownItem', () => {
onActivateProfileProxy={activate}
/>
);
const btn = screen.getByRole('button');
const btn = screen.getByRole("button");
await userEvent.click(btn);
expect(activate).toHaveBeenCalledWith(null);
expect(btn.querySelector('svg')).toBeInTheDocument();
expect(btn.querySelector("svg")).toBeInTheDocument();
});
});
2 changes: 1 addition & 1 deletion components/header/share/HeaderShare.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default function HeaderShare({
);
}

function HeaderQRModal({
export function HeaderQRModal({
show,
onClose,
}: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,26 @@ import {
faRightFromBracket,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { ShareIcon } from "@heroicons/react/24/outline";
import { AnimatePresence, motion } from "framer-motion";
import { useContext, useEffect, useState } from "react";
import { AuthContext } from "@/components/auth/Auth";
import { useSeizeConnectContext } from "@/components/auth/SeizeConnectContext";
import type { ApiIdentity } from "@/generated/models/ApiIdentity";
import type { ApiProfileProxy } from "@/generated/models/ApiProfileProxy";
import HeaderUserConnectedAccounts from "../connected/HeaderUserConnectedAccounts";
import HeaderUserConnectedAccounts from "./connected/HeaderUserConnectedAccounts";
import HeaderUserProxyDropdownItem from "./HeaderUserProxyDropdownItem";

export default function HeaderUserProxyDropdown({
export default function HeaderUserMenuDropdown({
isOpen,
profile,
onClose,
onOpenShare,
}: {
readonly isOpen: boolean;
readonly profile: ApiIdentity;
readonly onClose: () => void;
readonly onOpenShare?: (() => void) | undefined;
}) {
const {
address,
Expand Down Expand Up @@ -126,17 +129,14 @@ export default function HeaderUserProxyDropdown({
>
<div className="tw-mt-1 tw-w-full tw-overflow-hidden tw-rounded-md tw-bg-iron-800 tw-shadow-2xl">
<div className="tw-flow-root tw-overflow-y-auto tw-overflow-x-hidden tw-py-2">
<div
role="list"
className="tw-flex tw-flex-col tw-gap-y-2 tw-divide-x-0 tw-divide-y tw-divide-solid tw-divide-iron-700"
>
<ul className="tw-m-0 tw-flex tw-list-none tw-flex-col tw-gap-y-2 tw-divide-x-0 tw-divide-y tw-divide-solid tw-divide-iron-700 tw-p-0">
{availableConnectedAccounts.length > 0 && (
<div className="tw-mx-0 tw-flex tw-flex-col tw-gap-y-2 tw-px-2">
<li className="tw-mx-0 tw-flex tw-flex-col tw-gap-y-2 tw-px-2">
<HeaderUserConnectedAccounts
accounts={availableConnectedAccounts.map((account) => ({
...account,
unreadNotificationsCount:
connectedAccountUnreadNotifications[
connectedAccountUnreadNotifications?.[
account.address.toLowerCase()
] ?? 0,
}))}
Expand All @@ -151,10 +151,10 @@ export default function HeaderUserProxyDropdown({
});
}}
/>
</div>
</li>
)}
{hasProxySection && (
<div className="tw-mx-0 tw-flex tw-flex-col tw-gap-y-2 tw-px-2">
<li className="tw-mx-0 tw-flex tw-flex-col tw-gap-y-2 tw-px-2">
<p className="tw-m-0 tw-px-3 tw-pt-2 tw-text-xs tw-font-semibold tw-uppercase tw-tracking-wide tw-text-iron-500">
Proxy Profile
</p>
Expand All @@ -179,16 +179,16 @@ export default function HeaderUserProxyDropdown({
>
<img
src={profile.pfp}
alt="Profile Picture"
alt={`${label} avatar`}
className="tw-absolute tw-inset-0 tw-block tw-h-full tw-w-full tw-rounded-lg tw-bg-iron-700 tw-object-cover tw-transition tw-duration-300 tw-ease-out"
/>
</div>
) : (
<div
className={`${
!activeProfileProxy
? "tw-bg-iron-600"
: "tw-bg-iron-700 group-hover:tw-bg-iron-600"
activeProfileProxy
? "tw-bg-iron-700 group-hover:tw-bg-iron-600"
: "tw-bg-iron-600"
} tw-h-6 tw-w-6 tw-flex-none tw-flex-shrink-0 tw-rounded-lg tw-transition tw-duration-300 tw-ease-out`}
title={
activeProfileProxy
Expand Down Expand Up @@ -229,9 +229,9 @@ export default function HeaderUserProxyDropdown({
onActivateProfileProxy={onActivateProfileProxy}
/>
))}
</div>
</li>
)}
<div className="tw-h-full tw-px-2 tw-pt-2">
<li className="tw-h-full tw-px-2 tw-pt-2">
{isConnected ? (
<button
onClick={() => {
Expand Down Expand Up @@ -279,8 +279,22 @@ export default function HeaderUserProxyDropdown({
<span>Connect Wallet</span>
</button>
)}
</div>
<div className="tw-h-full tw-px-2 tw-pt-2">
</li>
{onOpenShare && (
<li className="tw-h-full tw-px-2 tw-pt-2">
<button
onClick={onOpenShare}
type="button"
aria-label="Share"
title="Share"
className="tw-relative tw-flex tw-h-full tw-w-full tw-cursor-pointer tw-select-none tw-items-center tw-gap-x-3 tw-rounded-lg tw-border-none tw-bg-transparent tw-px-3 tw-py-2.5 tw-text-left tw-text-md tw-font-medium tw-text-iron-300 tw-transition tw-duration-300 tw-ease-out hover:tw-bg-iron-700 hover:tw-text-iron-50 focus:tw-outline-none focus:tw-ring-1 focus:tw-ring-primary-400"
>
<ShareIcon className="tw-h-4 tw-w-4 tw-flex-shrink-0" />
<span>Share</span>
</button>
</li>
)}
<li className="tw-h-full tw-px-2 tw-pt-2">
<button
onClick={() => {
void runMenuAction({
Expand Down Expand Up @@ -326,8 +340,8 @@ export default function HeaderUserProxyDropdown({
<span>Sign Out All Profiles</span>
</button>
)}
</div>
</div>
</li>
</ul>
</div>
</div>
</motion.div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,38 @@ export default function HeaderUserProxyDropdownItem({
<button
type="button"
className={`${
!isActive
? "tw-bg-transparent hover:tw-bg-iron-700"
: "tw-bg-iron-700"
} tw-group tw-py-2.5 tw-w-full tw-h-full tw-border-none tw-text-left tw-flex tw-items-center tw-gap-x-3 tw-text-white tw-rounded-lg tw-relative tw-cursor-pointer tw-select-none tw-px-3 focus:tw-outline-none focus:tw-ring-1 focus:tw-ring-primary-400 tw-transition tw-duration-300 tw-ease-out`}
isActive ? "tw-bg-iron-700" : "tw-bg-transparent hover:tw-bg-iron-700"
} tw-group tw-relative tw-flex tw-h-full tw-w-full tw-cursor-pointer tw-select-none tw-items-center tw-gap-x-3 tw-rounded-lg tw-border-none tw-px-3 tw-py-2.5 tw-text-left tw-text-white tw-transition tw-duration-300 tw-ease-out focus:tw-outline-none focus:tw-ring-1 focus:tw-ring-primary-400`}
onClick={() => onActivateProfileProxy(isActive ? null : profileProxy)}
>
{profileProxy.created_by.pfp ? (
<img
src={profileProxy.created_by.pfp}
alt="Profile Picture"
className="tw-flex-shrink-0 tw-h-6 tw-w-6 tw-flex-none tw-rounded-lg tw-bg-iron-800"
alt={`${profileProxy.created_by.handle} avatar`}
className="tw-h-6 tw-w-6 tw-flex-none tw-flex-shrink-0 tw-rounded-lg tw-bg-iron-800"
/>
) : (
<div
className={`${
isActive
? "tw-bg-iron-600"
: "tw-bg-iron-700 group-hover:tw-bg-iron-600"
} tw-flex-shrink-0 tw-h-6 tw-w-6 tw-flex-none tw-rounded-lg tw-transition tw-duration-300 tw-ease-out`}
} tw-h-6 tw-w-6 tw-flex-none tw-flex-shrink-0 tw-rounded-lg tw-transition tw-duration-300 tw-ease-out`}
></div>
)}
<div className="tw-flex tw-justify-between tw-items-center tw-w-full">
<div className="tw-truncate tw-inline-flex tw-items-center tw-justify-between">
<div className="tw-flex tw-w-full tw-items-center tw-justify-between">
<div className="tw-inline-flex tw-items-center tw-justify-between tw-truncate">
<div className="tw-truncate tw-text-md tw-font-medium tw-text-white">
{profileProxy.created_by.handle}
</div>
<span className="tw-pl-2 tw-pr-0.5 tw-italic tw-text-sm tw-text-iron-400 tw-font-normal">
<span className="tw-pl-2 tw-pr-0.5 tw-text-sm tw-font-normal tw-italic tw-text-iron-400">
Proxy
</span>
</div>
<div>
{isActive && (
<svg
className="tw-flex-shrink-0 tw-h-5 tw-w-5 tw-ml-2 tw-text-primary-400 tw-transition tw-duration-300 tw-ease-out"
className="tw-ml-2 tw-h-5 tw-w-5 tw-flex-shrink-0 tw-text-primary-400 tw-transition tw-duration-300 tw-ease-out"
viewBox="0 0 24 24"
fill="none"
aria-hidden="true"
Expand Down
22 changes: 20 additions & 2 deletions components/layout/sidebar/WebSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import { usePathname } from "next/navigation";
import { useEffect, useMemo, useRef, useState } from "react";
import { Tooltip as ReactTooltip } from "react-tooltip";
import BellIcon from "@/components/common/icons/BellIcon";
import { useUnreadNotifications } from "@/hooks/useUnreadNotifications";
import { useIdentity } from "../../../hooks/useIdentity";
import { useAuth } from "../../auth/Auth";
import { useSeizeConnectContext } from "../../auth/SeizeConnectContext";
Expand Down Expand Up @@ -40,6 +42,9 @@ function WebSidebar({
handleOrWallet: address || "",
initialProfile: null,
});
const { haveUnreadNotifications } = useUnreadNotifications(
connectedProfile?.handle ?? null
);
const profilePath = useMemo(() => {
if (connectedProfile?.handle) return `/${connectedProfile.handle}`;
if (address) return `/${address}`;
Expand Down Expand Up @@ -175,8 +180,21 @@ function WebSidebar({
<WebSidebarNav ref={navRef} isCollapsed={shouldShowCollapsed} />
</div>

{profilePath && (
{address && (
<div className="tw-px-3 tw-pt-2">
<WebSidebarNavItem
href="/notifications"
icon={BellIcon}
active={pathname?.startsWith("/notifications") || false}
collapsed={shouldShowCollapsed}
label="Notifications"
hasIndicator={haveUnreadNotifications}
/>
</div>
)}

{profilePath && (
<div className="tw-px-3">
<WebSidebarNavItem
href={profilePath}
icon={UserIcon}
Expand All @@ -188,7 +206,7 @@ function WebSidebar({
</div>
)}

<HeaderShare isCollapsed={shouldShowCollapsed} />
{!address && <HeaderShare isCollapsed={shouldShowCollapsed} />}

<WebSidebarUser
isCollapsed={shouldShowCollapsed}
Expand Down
16 changes: 0 additions & 16 deletions components/layout/sidebar/WebSidebarNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { useAppWallets } from "@/components/app-wallets/AppWalletsContext";
import { useAuth } from "@/components/auth/Auth";
import BellIcon from "@/components/common/icons/BellIcon";
import ChatBubbleIcon from "@/components/common/icons/ChatBubbleIcon";
import HomeIcon from "@/components/common/icons/HomeIcon";
import WavesIcon from "@/components/common/icons/WavesIcon";
Expand All @@ -13,7 +12,6 @@ import CommonAnimationWrapper from "@/components/utils/animation/CommonAnimation
import useCapacitor from "@/hooks/useCapacitor";
import { useSectionMap, useSidebarSections } from "@/hooks/useSidebarSections";
import { useUnreadIndicator } from "@/hooks/useUnreadIndicator";
import { useUnreadNotifications } from "@/hooks/useUnreadNotifications";
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { usePathname } from "next/navigation";
import React, {
Expand Down Expand Up @@ -41,9 +39,6 @@ const WebSidebarNav = React.forwardRef<
const { country } = useCookieConsent();
const { connectedProfile } = useAuth();
const { appWalletsSupported } = useAppWallets();
const { haveUnreadNotifications } = useUnreadNotifications(
connectedProfile?.handle ?? null
);
const { hasUnread: hasUnreadMessages } = useUnreadIndicator({
type: "messages",
handle: connectedProfile?.handle ?? null,
Expand Down Expand Up @@ -286,17 +281,6 @@ const WebSidebarNav = React.forwardRef<
</li>
)}

<li>
<WebSidebarNavItem
href="/notifications"
icon={BellIcon}
active={pathname?.startsWith("/notifications") || false}
collapsed={isCollapsed}
label="Notifications"
hasIndicator={haveUnreadNotifications}
/>
</li>

<li>
<WebSidebarNavItem
onClick={(event?: React.MouseEvent) => {
Expand Down
Loading