added edit profile modal
This commit is contained in:
parent
6fb452f56b
commit
b0017440a0
@ -11,7 +11,9 @@ import ProfileFeed from "./_components/Feed";
|
||||
import Subscriptions from "./_components/Subscriptions";
|
||||
import { nip19 } from "nostr-tools";
|
||||
import useLists from "@/lib/hooks/useLists";
|
||||
|
||||
import EditProfileModal from "@/components/Modals/EditProfile";
|
||||
import { useModal } from "@/app/_providers/modal/provider";
|
||||
import useCurrentUser from "@/lib/hooks/useCurrentUser";
|
||||
export default function ProfilePage({
|
||||
params: { npub },
|
||||
}: {
|
||||
@ -19,10 +21,9 @@ export default function ProfilePage({
|
||||
npub: string;
|
||||
};
|
||||
}) {
|
||||
const modal = useModal();
|
||||
const { currentUser, follows } = useCurrentUser();
|
||||
const [activeTab, setActiveTab] = useState("feed");
|
||||
if (npub === "service-worker.js") {
|
||||
throw new Error("Invalid list");
|
||||
}
|
||||
const { type, data } = nip19.decode(npub);
|
||||
|
||||
if (type !== "npub") {
|
||||
@ -72,10 +73,26 @@ export default function ProfilePage({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Button size={"sm"} className="rounded-sm px-5 sm:hidden">
|
||||
Follow
|
||||
</Button>
|
||||
<Button className="rounded-sm px-5 max-sm:hidden">Follow</Button>
|
||||
<div className="flex items-center gap-3">
|
||||
{currentUser?.pubkey === pubkey && (
|
||||
<Button
|
||||
onClick={() => modal?.show(<EditProfileModal />)}
|
||||
variant={"outline"}
|
||||
className="rounded-sm px-5 max-sm:h-8 max-sm:text-xs"
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
)}
|
||||
{!follows.includes(pubkey) && (
|
||||
<Button
|
||||
onClick={() => modal?.show(<EditProfileModal />)}
|
||||
variant={"default"}
|
||||
className="rounded-sm px-5 max-sm:h-8 max-sm:text-xs"
|
||||
>
|
||||
Follow
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mx-auto max-w-[800px] space-y-1 px-4">
|
||||
<div className="flex items-center gap-x-1.5 lg:gap-x-2.5">
|
||||
|
121
components/Modals/EditProfile.tsx
Normal file
121
components/Modals/EditProfile.tsx
Normal file
@ -0,0 +1,121 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import FormModal from "./FormModal";
|
||||
import { z } from "zod";
|
||||
import useEvents from "@/lib/hooks/useEvents";
|
||||
import { createEvent } from "@/lib/actions/create";
|
||||
import { unixTimeNowInSeconds } from "@/lib/nostr/dates";
|
||||
import { useModal } from "@/app/_providers/modal/provider";
|
||||
import { toast } from "sonner";
|
||||
import { useNDK } from "@/app/_providers/ndk";
|
||||
import useCurrentUser from "@/lib/hooks/useCurrentUser";
|
||||
|
||||
const EditProfileSchema = z.object({
|
||||
display_name: z.string().optional(),
|
||||
name: z.string().optional(),
|
||||
image: z.string().optional(),
|
||||
about: z.string().optional(),
|
||||
banner: z.string().optional(),
|
||||
website: z.string().optional(),
|
||||
nip05: z.string().optional(),
|
||||
lud16: z.string().optional(),
|
||||
});
|
||||
|
||||
type EditProfileType = z.infer<typeof EditProfileSchema>;
|
||||
|
||||
export default function EditProfileModal() {
|
||||
const modal = useModal();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [sent, setSent] = useState(false);
|
||||
const { ndk } = useNDK();
|
||||
const { currentUser, updateUser } = useCurrentUser();
|
||||
const { events } = useEvents({
|
||||
filter: {
|
||||
kinds: [0],
|
||||
authors: [currentUser?.pubkey ?? ""],
|
||||
since: unixTimeNowInSeconds() - 10,
|
||||
limit: 1,
|
||||
},
|
||||
enabled: sent,
|
||||
});
|
||||
useEffect(() => {
|
||||
if (events.length) {
|
||||
console.log("Done!");
|
||||
setIsLoading(false);
|
||||
toast.success("Profile Updated!");
|
||||
modal?.hide();
|
||||
}
|
||||
}, [events]);
|
||||
|
||||
async function handleSubmit(userData: EditProfileType) {
|
||||
setIsLoading(true);
|
||||
const content = JSON.stringify(userData);
|
||||
const result = await createEvent(ndk!, {
|
||||
content,
|
||||
kind: 0,
|
||||
tags: [],
|
||||
});
|
||||
if (result) {
|
||||
updateUser(JSON.stringify({ ...userData, npub: currentUser?.npub }));
|
||||
}
|
||||
setSent(true);
|
||||
}
|
||||
|
||||
return (
|
||||
<FormModal
|
||||
title="Edit List"
|
||||
fields={[
|
||||
{
|
||||
label: "Display name",
|
||||
type: "input",
|
||||
slug: "display_name",
|
||||
},
|
||||
{
|
||||
label: "Name",
|
||||
type: "input",
|
||||
slug: "name",
|
||||
},
|
||||
{
|
||||
label: "Image",
|
||||
type: "input",
|
||||
slug: "image",
|
||||
},
|
||||
{
|
||||
label: "About",
|
||||
type: "text-area",
|
||||
slug: "about",
|
||||
},
|
||||
{
|
||||
label: "Banner",
|
||||
type: "input",
|
||||
slug: "banner",
|
||||
},
|
||||
{
|
||||
label: "Website",
|
||||
type: "input",
|
||||
slug: "website",
|
||||
},
|
||||
{
|
||||
label: "NIP-05",
|
||||
type: "input",
|
||||
slug: "nip05",
|
||||
placeholder: "name@example.com",
|
||||
},
|
||||
{
|
||||
label: "Bitcoin lightning address (lud16)",
|
||||
type: "input",
|
||||
slug: "lud16",
|
||||
},
|
||||
]}
|
||||
defaultValues={{
|
||||
...currentUser?.profile,
|
||||
display_name: currentUser?.profile?.displayName,
|
||||
}}
|
||||
formSchema={EditProfileSchema}
|
||||
onSubmit={handleSubmit}
|
||||
isSubmitting={isLoading}
|
||||
cta={{
|
||||
text: "Save Changes",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
@ -10,6 +10,17 @@ import useCurrentUser from "@/lib/hooks/useCurrentUser";
|
||||
import { HiOutlineLightningBolt } from "react-icons/hi";
|
||||
import { RiSubtractFill, RiAddFill } from "react-icons/ri";
|
||||
import { formatCount } from "@/lib/utils";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
|
||||
const intervals = [
|
||||
10, 25, 50, 75, 100, 150, 200, 250, 350, 500, 750, 1000, 1250, 1500, 2_000,
|
||||
2_500, 3_000, 3_500, 4_000, 5_000, 6_000, 7_500, 10_000, 12_500, 15_000,
|
||||
@ -20,6 +31,7 @@ export default function ZapPicker() {
|
||||
const { loginWithNip07 } = useNDK();
|
||||
const { loginWithPubkey, currentUser } = useCurrentUser();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [note, setNote] = useState("");
|
||||
const modal = useModal();
|
||||
const [sats, setSats] = useState(2000);
|
||||
|
||||
@ -59,6 +71,15 @@ export default function ZapPicker() {
|
||||
Satoshis
|
||||
</div>
|
||||
</div>
|
||||
<div className="">
|
||||
<FormLabel>Note</FormLabel>
|
||||
<Textarea
|
||||
placeholder="Add a note..."
|
||||
onChange={(e) => setNote(e.target.value)}
|
||||
value={note}
|
||||
className="auto-sizing"
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
|
@ -19,7 +19,7 @@ const UserSchema = z.object({
|
||||
name: z.string().optional(),
|
||||
username: z.string().optional(),
|
||||
display_name: z.string().optional(),
|
||||
picture: z.string().optional(),
|
||||
image: z.string().optional(),
|
||||
banner: z.string().optional(),
|
||||
about: z.string().optional(),
|
||||
website: z.string().optional(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user