Profile page barebones
This commit is contained in:
parent
b3a0ca7c7a
commit
f99e39c712
@ -1,12 +1,9 @@
|
||||
import {
|
||||
LaptopIcon,
|
||||
PersonIcon
|
||||
} from "@radix-ui/react-icons";
|
||||
import { LaptopIcon, PersonIcon } from "@radix-ui/react-icons";
|
||||
import { DropdownMenu, Flex, IconButton, Text } from "@radix-ui/themes";
|
||||
import { Icon } from "@radix-ui/themes/dist/esm/components/callout.js";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { userAtom } from "../../../../AtomStore/AtomStore";
|
||||
import LoginButton from "./LoginButton/LoginButton";
|
||||
import LogoutButton from "./LogoutButton/LogoutButton";
|
||||
@ -15,6 +12,8 @@ export default function UserButton() {
|
||||
const user = useAtomValue(userAtom);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<DropdownMenu.Root>
|
||||
@ -25,37 +24,33 @@ export default function UserButton() {
|
||||
</DropdownMenu.Trigger>
|
||||
|
||||
<DropdownMenu.Content className="w-fit">
|
||||
<DropdownMenu.Item>
|
||||
<Link to={"/user/:user-id/profile"}>
|
||||
<Flex className="justify-between gap-2">
|
||||
<DropdownMenu.Item onClick={() => navigate("/profile")}>
|
||||
<div>
|
||||
<Flex className="justify-between w-full gap-2">
|
||||
<Icon>
|
||||
<PersonIcon />
|
||||
</Icon>
|
||||
|
||||
<Text>{t("profile")}</Text>
|
||||
</Flex>
|
||||
</Link>
|
||||
</div>
|
||||
</DropdownMenu.Item>
|
||||
|
||||
<DropdownMenu.Item>
|
||||
<Link to={"/user/blogs"}>
|
||||
<DropdownMenu.Item onClick={() => navigate("/user/blogs")}>
|
||||
<div>
|
||||
<Flex className="justify-between gap-2">
|
||||
<Icon>
|
||||
<LaptopIcon />
|
||||
</Icon>
|
||||
<Text>{t("yourBlogs")}</Text>
|
||||
</Flex>
|
||||
</Link>
|
||||
</div>
|
||||
</DropdownMenu.Item>
|
||||
|
||||
<DropdownMenu.Separator />
|
||||
|
||||
<DropdownMenu.Item color={user ? "red" : "green"}>
|
||||
{user ? (
|
||||
<LogoutButton />
|
||||
) : (
|
||||
<LoginButton />
|
||||
)}
|
||||
{user ? <LogoutButton /> : <LoginButton />}
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
|
||||
123
enshi/src/Components/ProfileNavbar/ProfileNavbar.tsx
Normal file
123
enshi/src/Components/ProfileNavbar/ProfileNavbar.tsx
Normal file
@ -0,0 +1,123 @@
|
||||
import {
|
||||
BoxIcon,
|
||||
FileTextIcon,
|
||||
LockClosedIcon,
|
||||
PersonIcon
|
||||
} from "@radix-ui/react-icons";
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
Flex,
|
||||
Separator,
|
||||
TabNav,
|
||||
Text,
|
||||
} from "@radix-ui/themes";
|
||||
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
export default function ProfileNavbar() {
|
||||
const { hash, pathname } = useLocation();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
console.log(`pathname: ${pathname}, hash: ${hash}`);
|
||||
return (
|
||||
<>
|
||||
<Flex className="relative flex flex-col sm:hidden">
|
||||
<TabNav.Root size={"2"}>
|
||||
<TabNav.Link
|
||||
active={pathname === "/profile"}
|
||||
onClick={() => navigate("/profile")}
|
||||
>
|
||||
<Flex className="items-center gap-1">
|
||||
<Text>About</Text>
|
||||
</Flex>
|
||||
</TabNav.Link>
|
||||
|
||||
<TabNav.Link
|
||||
active={pathname === "/profile/sec"}
|
||||
onClick={() => navigate("/profile/sec")}
|
||||
>
|
||||
<Flex className="items-center gap-1">
|
||||
<Text>Security</Text>
|
||||
</Flex>
|
||||
</TabNav.Link>
|
||||
|
||||
<TabNav.Link
|
||||
active={pathname === "/profile/posts"}
|
||||
onClick={() => navigate("/profile/posts")}
|
||||
>
|
||||
<Flex className="items-center gap-1">
|
||||
<Text>Posts</Text>
|
||||
{/* <CaretDownIcon /> */}
|
||||
</Flex>
|
||||
</TabNav.Link>
|
||||
</TabNav.Root>
|
||||
</Flex>
|
||||
|
||||
<Flex
|
||||
direction={"column"}
|
||||
gap={"4"}
|
||||
className="absolute shrink collapse sm:relative sm:visible"
|
||||
>
|
||||
<Card>
|
||||
<Flex gap={"2"} direction={"column"}>
|
||||
<Flex direction={"row"} gap={"2"} align={"baseline"}>
|
||||
<Avatar fallback="TU" radius="full" />
|
||||
<Text>Test User</Text>
|
||||
</Flex>
|
||||
<Separator size={"4"} />
|
||||
<Flex gap={"2"}>
|
||||
<Badge>test</Badge>
|
||||
<Badge color="amber">user</Badge>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
|
||||
<Box className="mx-1">
|
||||
<Separator
|
||||
orientation={"horizontal"}
|
||||
size={"4"}
|
||||
className=""
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Flex gap={"2"} direction={"column"}>
|
||||
<Button
|
||||
className="relative"
|
||||
variant={pathname === "/profile" ? "solid" : "outline"}
|
||||
onClick={() => navigate("/profile")}
|
||||
>
|
||||
<PersonIcon className="absolute left-4" />
|
||||
<Text>About</Text>
|
||||
</Button>
|
||||
<Button
|
||||
variant={pathname === "/profile/sec" ? "solid" : "outline"}
|
||||
className="relative"
|
||||
onClick={() => navigate("/profile/sec")}
|
||||
>
|
||||
<LockClosedIcon className="absolute left-4" />
|
||||
<Text>Security</Text>
|
||||
</Button>
|
||||
<Button
|
||||
variant={pathname === "/profile/posts" ? "solid" : "outline"}
|
||||
className="relative"
|
||||
onClick={() => navigate("/profile/posts")}
|
||||
>
|
||||
<FileTextIcon className="absolute left-4" />
|
||||
<Text>Posts</Text>
|
||||
</Button>
|
||||
<Button variant="outline" className="relative">
|
||||
<BoxIcon className="absolute left-4" />
|
||||
<Text className="max-w-[60%]" truncate>
|
||||
Work in progress..qwflkqwhfkjqwhfkj.
|
||||
</Text>
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -63,7 +63,7 @@ export default function LoginPage() {
|
||||
return (
|
||||
<Card
|
||||
size={"2"}
|
||||
className="absolute w-1/4
|
||||
className="absolute w-[25rem] min-w-[20rem]
|
||||
left-[50%] top-[50%]
|
||||
translate-x-[-50%] translate-y-[-50%]"
|
||||
>
|
||||
|
||||
@ -7,10 +7,6 @@ import BlogCreationDialog from "../../Components/Dialogs/BlogCreationDialog/Blog
|
||||
import { JSONWithInt64 } from "../../utils/idnex";
|
||||
import SkeletonBoxes from "./SkeletonBoxes/SkeletonBoxes";
|
||||
|
||||
const TAGS = Array.from({ length: 50 }).map(
|
||||
(_, i, a) => `v1.2.0-beta.${a.length - i}`
|
||||
);
|
||||
|
||||
export default function UserBlogsPage() {
|
||||
const { data, isPending, isFetching } = useQuery({
|
||||
queryKey: ["userBlogs"],
|
||||
@ -52,16 +48,14 @@ export default function UserBlogsPage() {
|
||||
<ScrollArea.Viewport className="size-full">
|
||||
<Flex direction={"column"} gap={"2"}>
|
||||
{data
|
||||
? data?.map((blog: any, b) => {
|
||||
? data?.map((blog: any, b: number) => {
|
||||
return (
|
||||
<>
|
||||
<BlogBox
|
||||
key={b}
|
||||
title={blog.title}
|
||||
blogId={blog.blog_id}
|
||||
userId={blog.user_id}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
})
|
||||
: null}
|
||||
|
||||
8
enshi/src/Pages/UserPostsPage/UserPostsPage.tsx
Normal file
8
enshi/src/Pages/UserPostsPage/UserPostsPage.tsx
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
export default function UserPostsPage() {
|
||||
return (
|
||||
<div>
|
||||
<h1>User Posts Page</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
11
enshi/src/Pages/UserProfilePage/UserProfilePage.tsx
Normal file
11
enshi/src/Pages/UserProfilePage/UserProfilePage.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import { Box, Flex, Text } from "@radix-ui/themes";
|
||||
|
||||
export default function UserProfilePage() {
|
||||
return (
|
||||
<Flex direction={"column"} className="flex-grow-[8]">
|
||||
<Box className="flex-grow-[1]">
|
||||
<Text>This is user profile</Text>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
8
enshi/src/Pages/UserSecurityPage/UserSecurityPage.tsx
Normal file
8
enshi/src/Pages/UserSecurityPage/UserSecurityPage.tsx
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
export default function UserSecurityPage() {
|
||||
return (
|
||||
<div>
|
||||
<h1>User Security Page</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -12,10 +12,6 @@ const RETRY_INTERVAL_IN_SECONDS = 1;
|
||||
const SECONDS_IN_MINUTE = 60;
|
||||
const MILLS_IN_SECOND = 1000;
|
||||
|
||||
const TAGS = Array.from({ length: 50 }).map(
|
||||
(_, i, a) => `v1.2.0-beta.${a.length - i}`
|
||||
);
|
||||
|
||||
export default function MainPage() {
|
||||
const setUserData = useSetAtom(userAtom);
|
||||
|
||||
@ -65,7 +61,10 @@ export default function MainPage() {
|
||||
<Box flexGrow={"1"} className="flex-[1]">
|
||||
<NavBar />
|
||||
</Box>
|
||||
<Box flexGrow={"100"} className="flex overflow-hidden flex-">
|
||||
<Box
|
||||
flexGrow={"100"}
|
||||
className="flex flex-col overflow-hidden"
|
||||
>
|
||||
<Outlet />
|
||||
</Box>
|
||||
</Flex>
|
||||
|
||||
17
enshi/src/layout/ProfilePage/ProfilePage.tsx
Normal file
17
enshi/src/layout/ProfilePage/ProfilePage.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { Box, Flex, Separator } from "@radix-ui/themes";
|
||||
import { Outlet } from "react-router-dom";
|
||||
import ProfileNavbar from "../../Components/ProfileNavbar/ProfileNavbar";
|
||||
|
||||
export default function ProfilePage() {
|
||||
return (
|
||||
<Flex className="relative flex-col flex-1 gap-0 mx-4 sm:flex-row sm:gap-4 md:mx-32 lg:mx-60">
|
||||
<ProfileNavbar />
|
||||
|
||||
<Box className="my-2 collapse sm:visible">
|
||||
<Separator orientation="vertical" size={"4"} />
|
||||
</Box>
|
||||
|
||||
<Outlet />
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
@ -7,6 +7,7 @@ import {
|
||||
} from "react-router-dom";
|
||||
import ArticleViewer from "../Components/ArticleViewer/ArticleViewer";
|
||||
import MainPage from "../layout/MainPage/MainPage";
|
||||
import ProfilePage from "../layout/ProfilePage/ProfilePage";
|
||||
import AuthPageWrapper from "../Pages/AuthPageWrapper/AuthPageWrapper";
|
||||
import BlogPage from "../Pages/BlogPage/BlogPage";
|
||||
import LoginPage from "../Pages/LoginRegisterPage/LoginPage/LoginPage";
|
||||
@ -15,6 +16,9 @@ import RegisterPage from "../Pages/LoginRegisterPage/RegisterPage/RegisterPage";
|
||||
import PostCreatorPage from "../Pages/PostCreatorPage/PostCreatorPage";
|
||||
import RandomPostsPage from "../Pages/RandomPostsPage/RandomPostsPage";
|
||||
import UserBlogsPage from "../Pages/UserBlogsPage/UserBlogsPage";
|
||||
import UserPostsPage from "../Pages/UserPostsPage/UserPostsPage";
|
||||
import UserProfilePage from "../Pages/UserProfilePage/UserProfilePage";
|
||||
import UserSecurityPage from "../Pages/UserSecurityPage/UserSecurityPage";
|
||||
|
||||
function ErrorBoundary() {
|
||||
let error = useRouteError();
|
||||
@ -46,6 +50,21 @@ export const routes = createRoutesFromElements(
|
||||
}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="profile"
|
||||
element={
|
||||
<AuthPageWrapper>
|
||||
<ProfilePage />
|
||||
</AuthPageWrapper>
|
||||
}
|
||||
>
|
||||
<Route index element={<UserProfilePage />} />
|
||||
|
||||
<Route path="posts" element={<UserPostsPage />} />
|
||||
|
||||
<Route path='sec' element={<UserSecurityPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path="blogs/:blogId" element={<BlogPage />} />
|
||||
|
||||
<Route path="user" element={<Outlet />}>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user