mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-17 21:31:43 +01:00
add useless profile edit view
This commit is contained in:
parent
a3d85b705e
commit
89d1c13716
@ -21,6 +21,7 @@
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-error-boundary": "^3.1.4",
|
||||
"react-hook-form": "^7.41.2",
|
||||
"react-markdown": "^8.0.4",
|
||||
"react-router-dom": "^6.5.0",
|
||||
"react-singleton-hook": "^4.0.1",
|
||||
|
11
src/app.tsx
11
src/app.tsx
@ -6,6 +6,7 @@ import { Page } from "./components/page";
|
||||
import { SettingsView } from "./views/settings";
|
||||
import { GlobalView } from "./views/global";
|
||||
import { SetupView } from "./views/setup";
|
||||
import { ProfileView } from "./views/profile";
|
||||
import useSubject from "./hooks/use-subject";
|
||||
import identity from "./services/identity";
|
||||
|
||||
@ -54,6 +55,16 @@ export const App = () => {
|
||||
</RequireSetup>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/profile"
|
||||
element={
|
||||
<RequireSetup>
|
||||
<Page>
|
||||
<ProfileView />
|
||||
</Page>
|
||||
</RequireSetup>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
|
@ -16,12 +16,10 @@ import globalIcon from "./icons/global.svg";
|
||||
import settingsIcon from "./icons/settings.svg";
|
||||
import profileIcon from "./icons/profile.svg";
|
||||
import { useIsMobile } from "../hooks/use-is-mobile";
|
||||
import useSubject from "../hooks/use-subject";
|
||||
import identity from "../services/identity";
|
||||
import { ProfileButton } from "./profile-button";
|
||||
|
||||
const MobileLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
const navigate = useNavigate();
|
||||
const pubkey = useSubject(identity.pubkey);
|
||||
|
||||
return (
|
||||
<Flex direction="column" height="100%">
|
||||
@ -46,7 +44,7 @@ const MobileLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
<IconButton
|
||||
icon={<img src={profileIcon} />}
|
||||
aria-label="Profile"
|
||||
onClick={() => navigate(`/user/${pubkey}`)}
|
||||
onClick={() => navigate(`/profile`)}
|
||||
flexGrow="1"
|
||||
size="lg"
|
||||
/>
|
||||
@ -63,7 +61,6 @@ const MobileLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
};
|
||||
const DesktopLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
const navigate = useNavigate();
|
||||
const pubkey = useSubject(identity.pubkey);
|
||||
|
||||
return (
|
||||
<Container
|
||||
@ -74,8 +71,8 @@ const DesktopLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
overflow="hidden"
|
||||
>
|
||||
<VStack width="15rem" pt="2" alignItems="stretch" flexShrink={0}>
|
||||
<ProfileButton to="/profile" />
|
||||
<Button onClick={() => navigate("/")}>Home</Button>
|
||||
<Button onClick={() => navigate(`/user/${pubkey}`)}>Profile</Button>
|
||||
<Button onClick={() => navigate("/global")}>Global Feed</Button>
|
||||
<Button onClick={() => navigate("/settings")}>Settings</Button>
|
||||
<ConnectedRelays />
|
||||
|
35
src/components/profile-button.tsx
Normal file
35
src/components/profile-button.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { Box, LinkBox, Text } from "@chakra-ui/react";
|
||||
import { Link } from "react-router-dom";
|
||||
import useSubject from "../hooks/use-subject";
|
||||
import identity from "../services/identity";
|
||||
import { UserAvatar } from "./user-avatar";
|
||||
import { useUserMetadata } from "../hooks/use-user-metadata";
|
||||
|
||||
export type ProfileButtonProps = {
|
||||
to: string;
|
||||
};
|
||||
|
||||
export const ProfileButton = ({ to }: ProfileButtonProps) => {
|
||||
const pubkey = useSubject(identity.pubkey);
|
||||
const { loading, metadata } = useUserMetadata(pubkey);
|
||||
|
||||
return (
|
||||
<LinkBox
|
||||
as={Link}
|
||||
maxW="sm"
|
||||
p="2"
|
||||
borderWidth="1px"
|
||||
rounded="md"
|
||||
to={to}
|
||||
display="flex"
|
||||
gap="2"
|
||||
overflow="hidden"
|
||||
>
|
||||
<UserAvatar pubkey={pubkey} />
|
||||
<Box>
|
||||
<Text fontWeight="bold">{metadata?.name}</Text>
|
||||
<Text>{pubkey}</Text>
|
||||
</Box>
|
||||
</LinkBox>
|
||||
);
|
||||
};
|
95
src/views/profile/edit.tsx
Normal file
95
src/views/profile/edit.tsx
Normal file
@ -0,0 +1,95 @@
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
Flex,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
SkeletonText,
|
||||
Textarea,
|
||||
} from "@chakra-ui/react";
|
||||
import { useMemo } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import useSubject from "../../hooks/use-subject";
|
||||
import { useUserMetadata } from "../../hooks/use-user-metadata";
|
||||
import identity from "../../services/identity";
|
||||
|
||||
type FormData = {
|
||||
displayName?: string;
|
||||
username?: string;
|
||||
picture?: string;
|
||||
about?: string;
|
||||
};
|
||||
|
||||
type MetadataFormProps = {
|
||||
defaultValues?: FormData;
|
||||
onSubmit: (data: FormData) => void;
|
||||
};
|
||||
|
||||
const MetadataForm = ({ defaultValues, onSubmit }: MetadataFormProps) => {
|
||||
const { register, reset, handleSubmit, getValues } = useForm<FormData>({
|
||||
defaultValues,
|
||||
});
|
||||
|
||||
const submit = handleSubmit(onSubmit);
|
||||
|
||||
return (
|
||||
<form onSubmit={submit}>
|
||||
<Flex direction="column" gap="2" pt="4">
|
||||
<Flex gap="2">
|
||||
<FormControl>
|
||||
<FormLabel>Display Name</FormLabel>
|
||||
<Input {...register("displayName", { maxLength: 100 })} />
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>Username</FormLabel>
|
||||
<Input {...register("username", { maxLength: 100 })} />
|
||||
</FormControl>
|
||||
</Flex>
|
||||
<Flex gap="2" alignItems="center">
|
||||
<FormControl>
|
||||
<FormLabel>Picture</FormLabel>
|
||||
<Input {...register("picture", { maxLength: 150 })} />
|
||||
</FormControl>
|
||||
<Avatar src={getValues("picture")} size="md" />
|
||||
</Flex>
|
||||
<FormControl>
|
||||
<FormLabel>About</FormLabel>
|
||||
<Textarea
|
||||
placeholder="A short description"
|
||||
resize="vertical"
|
||||
rows={6}
|
||||
{...register("about")}
|
||||
/>
|
||||
</FormControl>
|
||||
<Flex alignSelf="flex-end" gap="2">
|
||||
<Button onClick={() => reset()}>Reset</Button>
|
||||
<Button colorScheme="teal" disabled>
|
||||
Save
|
||||
</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export const ProfileEditView = () => {
|
||||
const pubkey = useSubject(identity.pubkey);
|
||||
const { metadata, loading: loadingMetadata } = useUserMetadata(pubkey);
|
||||
|
||||
const defaultValues = useMemo<FormData>(
|
||||
() => ({
|
||||
displayName: metadata?.display_name,
|
||||
username: metadata?.name,
|
||||
picture: metadata?.picture,
|
||||
about: metadata?.about,
|
||||
}),
|
||||
[metadata]
|
||||
);
|
||||
|
||||
if (loadingMetadata) return <SkeletonText />;
|
||||
|
||||
const handleSubmit = (data: FormData) => {};
|
||||
|
||||
return <MetadataForm defaultValues={defaultValues} onSubmit={handleSubmit} />;
|
||||
};
|
10
src/views/profile/index.tsx
Normal file
10
src/views/profile/index.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import { Flex } from "@chakra-ui/react";
|
||||
import useSubject from "../../hooks/use-subject";
|
||||
import identity from "../../services/identity";
|
||||
import { ProfileEditView } from "./edit";
|
||||
|
||||
export const ProfileView = () => {
|
||||
const pubkey = useSubject(identity.pubkey);
|
||||
|
||||
return <ProfileEditView />;
|
||||
};
|
@ -4686,6 +4686,11 @@ react-focus-lock@^2.9.1:
|
||||
use-callback-ref "^1.3.0"
|
||||
use-sidecar "^1.1.2"
|
||||
|
||||
react-hook-form@^7.41.2:
|
||||
version "7.41.2"
|
||||
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.41.2.tgz#db37b0bfd844b96d7b30d26ed3c55366e3c2c7cd"
|
||||
integrity sha512-Uz5kNlfkEZve0sr5y2LsxPDGN3eNDjjKb1XJgand1E5Ay0S3zWo8YcJQNGu88/Zs6JaFnrJqTXbSr6B2q7wllA==
|
||||
|
||||
react-is@^16.13.1, react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
|
Loading…
x
Reference in New Issue
Block a user