added edit profile modal

This commit is contained in:
zmeyer44 2023-10-19 09:49:51 -04:00
parent 6fb452f56b
commit b0017440a0
4 changed files with 168 additions and 9 deletions

View File

@ -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">

View 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",
}}
/>
);
}

View File

@ -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"

View File

@ -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(),