From d8bda9866cffba753cd618ead64f07b6d341a3fc Mon Sep 17 00:00:00 2001 From: adi-codeartist001 Date: Tue, 26 May 2026 11:31:57 +0530 Subject: [PATCH 1/2] fix: change popup style - replace alert with toast (#18) --- src/components/ui/Toast.jsx | 25 +++++++++++++++++++++++++ src/pages/Profile.jsx | 7 ++++--- 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 src/components/ui/Toast.jsx diff --git a/src/components/ui/Toast.jsx b/src/components/ui/Toast.jsx new file mode 100644 index 0000000..06b4129 --- /dev/null +++ b/src/components/ui/Toast.jsx @@ -0,0 +1,25 @@ +import React, { useEffect } from "react"; + +const Toast = ({ message, type = "success", onClose }) => { + useEffect(() => { + const timer = setTimeout(onClose, 3000); + return () => clearTimeout(timer); + }, [onClose]); + + return ( +
+ {type === "success" ? "✅" : "❌"} + {message} +
+ ); +}; + +export default Toast; \ No newline at end of file diff --git a/src/pages/Profile.jsx b/src/pages/Profile.jsx index c207c17..d561df9 100644 --- a/src/pages/Profile.jsx +++ b/src/pages/Profile.jsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from "react"; +import Toast from "../components/ui/Toast"; import LottiePlayer from "../components/ui/LottiePlayer"; import { MapPin, @@ -26,7 +27,7 @@ export const Profile = () => { const { userData, user, setUserData } = useAuth(); const [copied, setCopied] = useState(false); const [rank, setRank] = useState("Loading..."); - + const [toast, setToast] = useState(null); // Social links edit states const [editingSocial, setEditingSocial] = useState(null); const [editValue, setEditValue] = useState(""); @@ -138,10 +139,10 @@ export const Profile = () => { setEditingSocial(null); setEditValue(""); - alert(`${type.charAt(0).toUpperCase() + type.slice(1)} updated successfully!`); + setToast({ message: `${type.charAt(0).toUpperCase() + type.slice(1)} updated successfully!`, type: "success" }); } catch (err) { console.error("Error updating social link:", err); - alert(`Failed to update ${type}. Please try again.`); + setToast({ message: `Failed to update ${type}. Please try again.`, type: "error" }); } finally { setUpdating(false); } From 66f1b66b0de65ec4c171be480d8f6cbc9d68c6f6 Mon Sep 17 00:00:00 2001 From: adi-codeartist001 Date: Tue, 26 May 2026 11:44:53 +0530 Subject: [PATCH 2/2] fix: add input validation for social links in profile (#17) --- src/pages/Profile.jsx | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/pages/Profile.jsx b/src/pages/Profile.jsx index d561df9..26f0739 100644 --- a/src/pages/Profile.jsx +++ b/src/pages/Profile.jsx @@ -83,9 +83,38 @@ export const Profile = () => { }; // Handle social link update - const handleUpdateSocialLink = async (type, value) => { +const handleUpdateSocialLink = async (type, value) => { if (!user) return; - + + // Validate input before updating + if (type === "linkedin") { + if (value && value.trim()) { + const linkedinPattern = /^(https?:\/\/)?(www\.)?linkedin\.com\/in\/[\w\-]+\/?$/i; + const rawVal = value.trim(); + const testVal = rawVal.startsWith('http') ? rawVal : 'https://' + rawVal; + if (!linkedinPattern.test(testVal)) { + setToast({ message: "Invalid LinkedIn URL. Use format: linkedin.com/in/username", type: "error" }); + return; + } + } + } else if (type === "instagram") { + if (value && value.trim()) { + const igPattern = /^@?[\w](?!.*?\.{2})[\w.]{1,28}[\w]$/; + if (!igPattern.test(value.trim())) { + setToast({ message: "Invalid Instagram username.", type: "error" }); + return; + } + } + } else if (type === "discord") { + if (value && value.trim()) { + const discordPattern = /^.{3,32}(#\d{4})?$/; + if (!discordPattern.test(value.trim())) { + setToast({ message: "Invalid Discord username.", type: "error" }); + return; + } + } + } + setUpdating(true); try { const userRef = doc(db, "users", user.uid);