Added a basic web UI
This commit is contained in:
19
client/src/components/app-icon/index.tsx
Normal file
19
client/src/components/app-icon/index.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
|
||||
export const AppIcon: React.FC = () => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
>
|
||||
<g fill="currentColor">
|
||||
<path d="M8 6c4.418 0 8-1.343 8-3s-3.582-3-8-3-8 1.343-8 3 3.582 3 8 3z" />
|
||||
<path d="M8 8c4.418 0 8-1.343 8-3v3c0 1.657-3.582 3-8 3S0 9.657 0 8V5c0 1.657 3.582 3 8 3z" />
|
||||
<path d="M8 13c4.418 0 8-1.343 8-3v3c0 1.657-3.582 3-8 3s-8-1.343-8-3v-3c0 1.657 3.582 3 8 3z" />
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
98
client/src/components/header/index.tsx
Normal file
98
client/src/components/header/index.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
import { DownOutlined } from "@ant-design/icons";
|
||||
import type { RefineThemedLayoutV2HeaderProps } from "@refinedev/antd";
|
||||
import { useGetIdentity, useGetLocale, useSetLocale } from "@refinedev/core";
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
Dropdown,
|
||||
Layout as AntdLayout,
|
||||
MenuProps,
|
||||
Space,
|
||||
Switch,
|
||||
theme,
|
||||
Typography,
|
||||
} from "antd";
|
||||
import React, { useContext } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ColorModeContext } from "../../contexts/color-mode";
|
||||
|
||||
const { Text } = Typography;
|
||||
const { useToken } = theme;
|
||||
|
||||
type IUser = {
|
||||
id: number;
|
||||
name: string;
|
||||
avatar: string;
|
||||
};
|
||||
|
||||
export const Header: React.FC<RefineThemedLayoutV2HeaderProps> = ({
|
||||
sticky,
|
||||
}) => {
|
||||
const { token } = useToken();
|
||||
const { i18n } = useTranslation();
|
||||
const locale = useGetLocale();
|
||||
const changeLanguage = useSetLocale();
|
||||
const { data: user } = useGetIdentity<IUser>();
|
||||
const { mode, setMode } = useContext(ColorModeContext);
|
||||
|
||||
const currentLocale = locale();
|
||||
|
||||
const menuItems: MenuProps["items"] = [...(i18n.languages || [])]
|
||||
.sort()
|
||||
.map((lang: string) => ({
|
||||
key: lang,
|
||||
onClick: () => changeLanguage(lang),
|
||||
icon: (
|
||||
<span style={{ marginRight: 8 }}>
|
||||
<Avatar size={16} src={`/images/flags/${lang}.svg`} />
|
||||
</span>
|
||||
),
|
||||
label: lang === "en" ? "English" : "German",
|
||||
}));
|
||||
|
||||
const headerStyles: React.CSSProperties = {
|
||||
backgroundColor: token.colorBgElevated,
|
||||
display: "flex",
|
||||
justifyContent: "flex-end",
|
||||
alignItems: "center",
|
||||
padding: "0px 24px",
|
||||
height: "64px",
|
||||
};
|
||||
|
||||
if (sticky) {
|
||||
headerStyles.position = "sticky";
|
||||
headerStyles.top = 0;
|
||||
headerStyles.zIndex = 1;
|
||||
}
|
||||
|
||||
return (
|
||||
<AntdLayout.Header style={headerStyles}>
|
||||
<Space>
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: menuItems,
|
||||
selectedKeys: currentLocale ? [currentLocale] : [],
|
||||
}}
|
||||
>
|
||||
<Button type="text">
|
||||
<Space>
|
||||
<Avatar size={16} src={`/images/flags/${currentLocale}.svg`} />
|
||||
{currentLocale === "en" ? "English" : "German"}
|
||||
<DownOutlined />
|
||||
</Space>
|
||||
</Button>
|
||||
</Dropdown>
|
||||
<Switch
|
||||
checkedChildren="🌛"
|
||||
unCheckedChildren="🔆"
|
||||
onChange={() => setMode(mode === "light" ? "dark" : "light")}
|
||||
defaultChecked={mode === "dark"}
|
||||
/>
|
||||
<Space style={{ marginLeft: "8px" }} size="middle">
|
||||
{user?.name && <Text strong>{user.name}</Text>}
|
||||
{user?.avatar && <Avatar src={user?.avatar} alt={user?.name} />}
|
||||
</Space>
|
||||
</Space>
|
||||
</AntdLayout.Header>
|
||||
);
|
||||
};
|
||||
1
client/src/components/index.ts
Normal file
1
client/src/components/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { Header } from "./header";
|
||||
Reference in New Issue
Block a user