From 4b016c908dda2019f3bf89e5a3d2eae535e5fbd2 Mon Sep 17 00:00:00 2001 From: polwex Date: Thu, 18 Sep 2025 00:24:39 +0700 Subject: oioi --- front/src/components/profile/Editor.tsx | 262 ++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 front/src/components/profile/Editor.tsx (limited to 'front/src/components/profile/Editor.tsx') diff --git a/front/src/components/profile/Editor.tsx b/front/src/components/profile/Editor.tsx new file mode 100644 index 0000000..2e4aebc --- /dev/null +++ b/front/src/components/profile/Editor.tsx @@ -0,0 +1,262 @@ +import { useState } from "react"; +import type { UserProfile, UserType } from "@/types/nostrill"; +import useLocalState from "@/state/state"; +import Icon from "@/components/Icon"; +import toast from "react-hot-toast"; +import Avatar from "../Avatar"; + +interface ProfileEditorProps { + user: UserType; + userString: string; + profile: UserProfile | undefined; + onSave?: () => void; +} + +const ProfileEditor: React.FC = ({ + user, + profile, + userString, + onSave, +}) => { + const { api, profiles } = useLocalState((s) => ({ + api: s.api, + pubkey: s.pubkey, + profiles: s.profiles, + })); + + // Initialize state with existing profile or defaults + const [name, setName] = useState(profile?.name || userString); + const [picture, setPicture] = useState(profile?.picture || ""); + const [about, setAbout] = useState(profile?.about || ""); + const [customFields, setCustomFields] = useState< + Array<{ key: string; value: string }> + >( + Object.entries(profile?.other || {}).map(([key, value]) => ({ + key, + value, + })), + ); + const [isEditing, setIsEditing] = useState(false); + const [isSaving, setIsSaving] = useState(false); + + const handleAddCustomField = () => { + setCustomFields([...customFields, { key: "", value: "" }]); + }; + + const handleUpdateCustomField = ( + index: number, + field: "key" | "value", + newValue: string, + ) => { + const updated = [...customFields]; + updated[index][field] = newValue; + setCustomFields(updated); + }; + + const handleRemoveCustomField = (index: number) => { + setCustomFields(customFields.filter((_, i) => i !== index)); + }; + + const handleSave = async () => { + setIsSaving(true); + try { + // Convert custom fields array to object + const other: Record = {}; + customFields.forEach(({ key, value }) => { + if (key.trim()) { + other[key.trim()] = value; + } + }); + + const nprofile: UserProfile = { + name, + picture, + about, + other, + }; + + // Call API to save profile + if (api && typeof api.createProfile === "function") { + await api.createProfile(nprofile); + } else { + throw new Error("Profile update API not available"); + } + + toast.success("Profile updated successfully"); + setIsEditing(false); + onSave?.(); + } catch (error) { + toast.error("Failed to update profile"); + console.error("Failed to save profile:", error); + } finally { + setIsSaving(false); + } + }; + + const handleCancel = () => { + // Reset to original values + const profile = profiles.get(userString); + if (profile) { + setName(profile.name || userString); + setPicture(profile.picture || ""); + setAbout(profile.about || ""); + setCustomFields( + Object.entries(profile.other || {}).map(([key, value]) => ({ + key, + value, + })), + ); + } + setIsEditing(false); + }; + console.log({ profile }); + console.log({ name, picture, customFields }); + + return ( +
+
+

Edit Profile

+ {!isEditing && ( + + )} +
+ + {isEditing ? ( +
+
+ + setName(e.target.value)} + placeholder="Your display name" + /> +
+ +
+ + setPicture(e.target.value)} + placeholder="https://example.com/avatar.jpg" + /> +
+ {picture ? ( + + ) : ( + + )} +
+
+ +
+ +