diff options
Diffstat (limited to 'front/src/components/ProfileEditor.tsx')
-rw-r--r-- | front/src/components/ProfileEditor.tsx | 280 |
1 files changed, 0 insertions, 280 deletions
diff --git a/front/src/components/ProfileEditor.tsx b/front/src/components/ProfileEditor.tsx deleted file mode 100644 index 9a7493f..0000000 --- a/front/src/components/ProfileEditor.tsx +++ /dev/null @@ -1,280 +0,0 @@ -import { useState, useEffect } from "react"; -import type { UserProfile } 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 { - ship: string; - onSave?: () => void; -} - -const ProfileEditor: React.FC<ProfileEditorProps> = ({ ship, onSave }) => { - const { api, profiles } = useLocalState((s) => ({ - api: s.api, - profiles: s.profiles, - })); - const isOwnProfile = ship === api?.airlock.our; - - // Initialize state with existing profile or defaults - const existingProfile = profiles.get(ship); - const [name, setName] = useState(existingProfile?.name || ""); - const [picture, setPicture] = useState(existingProfile?.picture || ""); - const [about, setAbout] = useState(existingProfile?.about || ""); - const [customFields, setCustomFields] = useState< - Array<{ key: string; value: string }> - >( - Object.entries(existingProfile?.other || {}).map(([key, value]) => ({ - key, - value, - })), - ); - const [isEditing, setIsEditing] = useState(false); - const [isSaving, setIsSaving] = useState(false); - - useEffect(() => { - const profile = profiles.get(ship); - if (profile) { - setName(profile.name || ""); - setPicture(profile.picture || ""); - setAbout(profile.about || ""); - setCustomFields( - Object.entries(profile.other || {}).map(([key, value]) => ({ - key, - value, - })), - ); - } - }, [ship, profiles]); - - 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<string, string> = {}; - customFields.forEach(({ key, value }) => { - if (key.trim()) { - other[key.trim()] = value; - } - }); - - const profile: UserProfile = { - name, - picture, - about, - other, - }; - - // Call API to save profile - if (api && typeof api.createProfile === "function") { - await api.createProfile(profile); - } 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(ship); - if (profile) { - setName(profile.name || ""); - setPicture(profile.picture || ""); - setAbout(profile.about || ""); - setCustomFields( - Object.entries(profile.other || {}).map(([key, value]) => ({ - key, - value, - })), - ); - } - setIsEditing(false); - }; - - if (!isOwnProfile) { - // View-only mode for other users' profiles - no editing allowed - return ( - <div className="profile-editor view-mode"> - <div className="profile-picture"> - <Avatar p={ship} size={120} picOnly={true} /> - </div> - <div className="profile-info"> - <h2>{name || ship}</h2> - {about && <p className="profile-about">{about}</p>} - - {customFields.length > 0 && ( - <div className="profile-custom-fields"> - <h4>Additional Info</h4> - {customFields.map(({ key, value }, index) => ( - <div key={index} className="custom-field-view"> - <span className="field-key">{key}:</span> - <span className="field-value">{value}</span> - </div> - ))} - </div> - )} - </div> - </div> - ); - } - - return ( - <div className="profile-editor"> - <div className="profile-header"> - <h2>Edit Profile</h2> - {isOwnProfile && !isEditing && ( - <button onClick={() => setIsEditing(true)} className="edit-btn"> - <Icon name="settings" size={16} /> - Edit - </button> - )} - </div> - - {isEditing ? ( - <div className="profile-form"> - <div className="form-group"> - <label htmlFor="name">Display Name</label> - <input - id="name" - type="text" - value={name} - onChange={(e) => setName(e.target.value)} - placeholder="Your display name" - /> - </div> - - <div className="form-group"> - <label htmlFor="picture">Profile Picture URL</label> - <input - id="picture" - type="url" - value={picture} - onChange={(e) => setPicture(e.target.value)} - placeholder="https://example.com/avatar.jpg" - /> - <div className="picture-preview"> - <Avatar p={ship} size={54} picOnly={true} /> - </div> - </div> - - <div className="form-group"> - <label htmlFor="about">About</label> - <textarea - id="about" - value={about} - onChange={(e) => setAbout(e.target.value)} - placeholder="Tell us about yourself..." - rows={4} - /> - </div> - - <div className="form-group custom-fields"> - <label>Custom Fields</label> - {customFields.map((field, index) => ( - <div key={index} className="custom-field-row"> - <input - type="text" - value={field.key} - onChange={(e) => - handleUpdateCustomField(index, "key", e.target.value) - } - placeholder="Field name" - className="field-key-input" - /> - <input - type="text" - value={field.value} - onChange={(e) => - handleUpdateCustomField(index, "value", e.target.value) - } - placeholder="Field value" - className="field-value-input" - /> - <button - onClick={() => handleRemoveCustomField(index)} - className="remove-field-btn" - title="Remove field" - > - × - </button> - </div> - ))} - <button onClick={handleAddCustomField} className="add-field-btn"> - + Add Custom Field - </button> - </div> - - <div className="form-actions"> - <button - onClick={handleSave} - disabled={isSaving} - className="save-btn" - > - {isSaving ? "Saving..." : "Save Profile"} - </button> - <button - onClick={handleCancel} - disabled={isSaving} - className="cancel-btn" - > - Cancel - </button> - </div> - </div> - ) : ( - <div className="profile-view"> - <div className="profile-picture"> - <Avatar p={ship} size={120} picOnly={true} /> - </div> - - <div className="profile-info"> - <h3>{name || ship}</h3> - {about && <p className="profile-about">{about}</p>} - - {customFields.length > 0 && ( - <div className="profile-custom-fields"> - <h4>Additional Info</h4> - {customFields.map(({ key, value }, index) => ( - <div key={index} className="custom-field-view"> - <span className="field-key">{key}:</span> - <span className="field-value">{value}</span> - </div> - ))} - </div> - )} - </div> - </div> - )} - </div> - ); -}; - -export default ProfileEditor; |