import { useEffect, useRef, useState } from "preact/hooks"; import { decryptDataWithStoredPassword, encryptDataWithStoredPassword, getEncryptionPassword, } from "../helpers.ts"; import { User } from "../db/interfaces.ts"; interface UserProfileEditProps { user: User; isEncrypted: boolean; } export default function UserProfileEdit( { user, isEncrypted }: UserProfileEditProps, ) { const [form, setForm] = useState({ ...user }); const [errors, setErrors] = useState<{ name?: string; email?: string }>({}); const [isEncryptionEnabled, setIsEncryptionEnabled] = useState(isEncrypted); const formRef = useRef(null); // Check if encryption is available and decrypt data on component mount useEffect(() => { const initializeComponent = async () => { const encryptionEnabled = getEncryptionPassword(user.id); setIsEncryptionEnabled(encryptionEnabled !== null); // If encryption is enabled and user has encrypted data, decrypt and populate fields if (encryptionEnabled && user.encrypted_data) { try { const decryptedData = await decryptDataWithStoredPassword( user.id, user.encrypted_data, ); if (decryptedData) { const encryptedDataObj = JSON.parse(decryptedData); // Only update form state with fields that have actual data from decrypted object const updatedFields: Partial = {}; if (encryptedDataObj.address_1) { updatedFields.address_1 = encryptedDataObj.address_1; } if (encryptedDataObj.address_2) { updatedFields.address_2 = encryptedDataObj.address_2; } if (encryptedDataObj.city) { updatedFields.city = encryptedDataObj.city; } if (encryptedDataObj.state) { updatedFields.state = encryptedDataObj.state; } if (encryptedDataObj.zip) updatedFields.zip = encryptedDataObj.zip; if (encryptedDataObj.country) { updatedFields.country = encryptedDataObj.country; } setForm((prevForm) => ({ ...prevForm, ...updatedFields, })); } } catch (error) { console.error("Failed to decrypt user data:", error); // Continue with original user data if decryption fails } } }; initializeComponent(); }, [user.id, user.encrypted_data]); function handleChange(e: Event) { const target = e.target as HTMLInputElement; setForm({ ...form, [target.name]: target.value }); setErrors({ ...errors, [target.name]: undefined }); } async function handleSave(e: Event) { e.preventDefault(); // Validate required fields const newErrors: { [key: string]: string } = {}; if (!form.name?.trim()) newErrors.name = "Name is required"; if (!form.email?.trim()) newErrors.email = "Email is required"; if (Object.keys(newErrors).length > 0) { setErrors(newErrors); return; } setErrors({}); // Prepare data for submission const submissionData = { ...form }; // Handle encryption if enabled if (isEncryptionEnabled) { const dataToEncrypt = { user_id: user.id, address_1: form.address_1 || "", address_2: form.address_2 || "", city: form.city || "", state: form.state || "", zip: form.zip || "", country: form.country || "", }; try { const encryptedData = await encryptDataWithStoredPassword( user.id, JSON.stringify(dataToEncrypt), ); if (encryptedData) { submissionData.encrypted_data = encryptedData; // Clear address fields when encryption is used submissionData.address_1 = ""; submissionData.address_2 = ""; submissionData.city = ""; submissionData.state = ""; submissionData.zip = ""; submissionData.country = ""; } } catch (error) { console.error("Encryption failed:", error); alert("Failed to encrypt data. Please try again."); return; } } // Get the form element using the ref const formElement = formRef.current; if (!formElement) return; // Update form field values with submission data (including encrypted data) Object.entries(submissionData).forEach(([key, value]) => { const input = formElement.querySelector( `[name="${key}"]`, ) as HTMLInputElement; if (input && value !== null && value !== undefined) { input.value = String(value); } }); // Submit the existing form formElement.submit(); } return ( <>

Profile

{isEncryptionEnabled && (
Encryption Enabled

Address information will be encrypted before saving.

)}

Mailing Address

); }