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