From e9ca1d96b258ae2f048a4396600bcf28960ec8d6 Mon Sep 17 00:00:00 2001 From: yawn <69970183+yawn-c111@users.noreply.github.com> Date: Tue, 3 Dec 2024 02:03:25 +0900 Subject: [PATCH] add: Header --- pkgs/frontend/app/components/CommonIcon.tsx | 45 +++++++++ pkgs/frontend/app/components/Header.tsx | 95 ++++++++++++++++++- pkgs/frontend/app/components/UserIcon.tsx | 21 ++++ .../frontend/app/components/WorkspaceIcon.tsx | 28 ++++++ pkgs/frontend/app/root.tsx | 2 +- pkgs/frontend/app/routes/_index.tsx | 2 +- 6 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 pkgs/frontend/app/components/CommonIcon.tsx create mode 100644 pkgs/frontend/app/components/UserIcon.tsx create mode 100644 pkgs/frontend/app/components/WorkspaceIcon.tsx diff --git a/pkgs/frontend/app/components/CommonIcon.tsx b/pkgs/frontend/app/components/CommonIcon.tsx new file mode 100644 index 0000000..2a94a5c --- /dev/null +++ b/pkgs/frontend/app/components/CommonIcon.tsx @@ -0,0 +1,45 @@ +import { useState, useEffect, ReactNode } from "react"; +import { Box, Image } from "@chakra-ui/react"; + +interface CommonIconProps { + imageUrl: string | undefined; + size: number; + fallbackIconComponent?: ReactNode; +} + +export const CommonIcon = ({ + size, + imageUrl, + fallbackIconComponent, +}: CommonIconProps) => { + const [showFallbackIcon, setShowFallbackIcon] = useState(!imageUrl); + + useEffect(() => { + setShowFallbackIcon(!imageUrl); + }, [imageUrl]); + + return ( + + {!showFallbackIcon ? ( + setShowFallbackIcon(true)} + /> + ) : ( + fallbackIconComponent || null + )} + + ); +}; diff --git a/pkgs/frontend/app/components/Header.tsx b/pkgs/frontend/app/components/Header.tsx index ed27af8..f3f3314 100644 --- a/pkgs/frontend/app/components/Header.tsx +++ b/pkgs/frontend/app/components/Header.tsx @@ -1,3 +1,96 @@ +import { useState, useEffect } from "react"; +import { Box, Text } from "@chakra-ui/react"; +import { WorkspaceIcon } from "./WorkspaceIcon"; +import { UserIcon } from "./UserIcon"; +import { useLocation } from "@remix-run/react"; + +const NO_HEADER_PATHS: string[] = ["/login"]; // 適宜ヘッダーが不要なページのパスを追加 +const HEADER_SIZE: number = 12; // 偶数のnumberだとアイコンが対応しているため望ましい + +const headerTextStyle = { + my: "auto", + wordBreak: "break-word", + flex: "1", +}; + +enum HeaderType { + NonHeader = "NonHeader", + UserIconOnly = "UserIconOnly", + WorkspaceAndUserIcons = "WorkspaceAndUserIcons", +} + export const Header = () => { - return
Header
; + const [headerType, setHeaderType] = useState( + HeaderType.NonHeader + ); + + const { pathname } = useLocation(); + + // ToDo: ページのパスや hooks で柔軟にロジックを実装する(切り替えてテストできます) + const isWalletConnected = true; + const isUserTobanEnsFound = true; + const isWorkspaceSelected = true; + + // ToDo: ユーザーやワークスペースごとの各種データを取得するロジックを実装する + const userImageUrl: string | undefined = undefined; + const workspaceName: string | undefined = "Workspace Name"; + const workspaceImageUrl: string | undefined = undefined; + + useEffect(() => { + const determineHeaderType = () => { + if ( + !NO_HEADER_PATHS.includes(pathname) && + isWalletConnected && + isUserTobanEnsFound + ) { + return isWorkspaceSelected && workspaceName + ? HeaderType.WorkspaceAndUserIcons + : HeaderType.UserIconOnly; + } + return HeaderType.NonHeader; + }; + + setHeaderType(determineHeaderType()); + }, [ + pathname, + isWalletConnected, + isUserTobanEnsFound, + isWorkspaceSelected, + workspaceName, + ]); + + return ( + + {headerType !== HeaderType.NonHeader && ( + <> + + {headerType === HeaderType.UserIconOnly && ( + + Workspaces + + )} + {headerType === HeaderType.WorkspaceAndUserIcons && ( + <> + + + {workspaceName} + + + )} + + + + )} + + ); }; diff --git a/pkgs/frontend/app/components/UserIcon.tsx b/pkgs/frontend/app/components/UserIcon.tsx new file mode 100644 index 0000000..01aa3b9 --- /dev/null +++ b/pkgs/frontend/app/components/UserIcon.tsx @@ -0,0 +1,21 @@ +import { FaCircleUser } from "react-icons/fa6"; +import { CommonIcon } from "./CommonIcon"; + +interface UserIconProps { + userImageUrl: string | undefined; + size: number; +} + +export const UserIcon = ({ userImageUrl, size }: UserIconProps) => { + return ( + + } + /> + ); +}; diff --git a/pkgs/frontend/app/components/WorkspaceIcon.tsx b/pkgs/frontend/app/components/WorkspaceIcon.tsx new file mode 100644 index 0000000..7ac9db2 --- /dev/null +++ b/pkgs/frontend/app/components/WorkspaceIcon.tsx @@ -0,0 +1,28 @@ +import { FaPeopleGroup } from "react-icons/fa6"; +import { CommonIcon } from "./CommonIcon"; + +interface WorkspaceIconProps { + workspaceImageUrl?: string; + size: number; +} + +export const WorkspaceIcon = ({ + workspaceImageUrl, + size, +}: WorkspaceIconProps) => { + return ( + + } + /> + ); +}; diff --git a/pkgs/frontend/app/root.tsx b/pkgs/frontend/app/root.tsx index 189e165..10f4b9b 100644 --- a/pkgs/frontend/app/root.tsx +++ b/pkgs/frontend/app/root.tsx @@ -33,7 +33,7 @@ export const Layout = withEmotionCache((props: LayoutProps, cache) => { - +
{children} diff --git a/pkgs/frontend/app/routes/_index.tsx b/pkgs/frontend/app/routes/_index.tsx index bee43b9..78a1933 100644 --- a/pkgs/frontend/app/routes/_index.tsx +++ b/pkgs/frontend/app/routes/_index.tsx @@ -27,7 +27,7 @@ export default function Index() { }; return ( - + BigBang