From 77cd35a8c85a89ff90330cf1852c39b9cb99b63a Mon Sep 17 00:00:00 2001 From: Deepak Pandey Date: Mon, 15 Sep 2025 09:53:55 +0530 Subject: [PATCH 1/2] fix: Improve UI and fix username validation issues - Replace 'CU' logo with proper CodeUnia logo component - Fix username validation to use direct database queries instead of RPC - Remove problematic regex pattern attribute causing console errors - Implement client-side random username generation - Add comprehensive username validation with visual feedback - Improve form styling with modern glassmorphism design - Add username preview and real-time validation indicators - Fix TypeScript errors and improve error handling Resolves console errors and improves user experience --- app/complete-profile/page.tsx | 254 ++++++++++++++++++++++------------ 1 file changed, 169 insertions(+), 85 deletions(-) diff --git a/app/complete-profile/page.tsx b/app/complete-profile/page.tsx index c99d48eb..27e413f7 100644 --- a/app/complete-profile/page.tsx +++ b/app/complete-profile/page.tsx @@ -5,6 +5,9 @@ import { useRouter } from 'next/navigation'; import Link from 'next/link'; import { createClient } from '@/lib/supabase/client'; import { toast } from 'sonner'; +import CodeuniaLogo from '@/components/codeunia-logo'; +import { InputValidator } from '@/lib/security/input-validation'; +import { CheckCircle, XCircle, AlertCircle, Loader2, Sparkles } from 'lucide-react'; interface User { id: string; @@ -25,6 +28,7 @@ export default function CompleteProfile() { const [isLoading, setIsLoading] = useState(false); const [isCheckingUsername, setIsCheckingUsername] = useState(false); const [usernameAvailable, setUsernameAvailable] = useState(null); + const [usernameError, setUsernameError] = useState(''); const [user, setUser] = useState(null); const [isValidating, setIsValidating] = useState(true); const router = useRouter(); @@ -101,21 +105,42 @@ export default function CompleteProfile() { }, []); const checkUsernameAvailability = async (usernameToCheck: string) => { - if (!usernameToCheck || usernameToCheck.length < 3) { + const clean = usernameToCheck.trim(); + + // First validate the username format + const validation = InputValidator.validateUsername(clean); + if (!validation.isValid) { + setUsernameError(validation.error || 'Invalid username'); + setUsernameAvailable(false); + return; + } + + setUsernameError(''); + + if (!clean || clean.length < 3) { setUsernameAvailable(null); return; } setIsCheckingUsername(true); try { - const clean = usernameToCheck.trim(); - const { data: isAvailable } = await getSupabaseClient().rpc('check_username_availability', { - username_param: clean - }); - setUsernameAvailable(isAvailable); + // Use direct query instead of RPC function (same approach as UsernameField component) + const { data, error } = await getSupabaseClient() + .from('profiles') + .select('username') + .eq('username', clean) + .single(); + + if (error && error.code !== 'PGRST116') { + throw error; + } + + // If no data found, username is available + setUsernameAvailable(!data); } catch (error) { console.error('Error checking username:', error); setUsernameAvailable(null); + setUsernameError('Unable to check username availability'); } finally { setIsCheckingUsername(false); } @@ -123,9 +148,10 @@ export default function CompleteProfile() { const handleUsernameChange = (value: string) => { setUsername(value); + setUsernameError(''); // Clear previous errors if (usernameCheckTimeout.current) clearTimeout(usernameCheckTimeout.current); usernameCheckTimeout.current = setTimeout(() => { - checkUsernameAvailability(value.trim()); + checkUsernameAvailability(value); }, 500); }; @@ -199,11 +225,17 @@ export default function CompleteProfile() { const generateRandomUsername = async () => { try { - const { data: randomUsername } = await getSupabaseClient().rpc('generate_safe_username'); - if (randomUsername) { - setUsername(randomUsername); - checkUsernameAvailability(randomUsername); - } + // Generate a simple random username since RPC might not be available + const adjectives = ['cool', 'smart', 'bright', 'quick', 'bold', 'wise', 'keen', 'sharp']; + const nouns = ['coder', 'dev', 'builder', 'creator', 'maker', 'hacker', 'ninja', 'wizard']; + const numbers = Math.floor(Math.random() * 9999); + + const adjective = adjectives[Math.floor(Math.random() * adjectives.length)]; + const noun = nouns[Math.floor(Math.random() * nouns.length)]; + const randomUsername = `${adjective}${noun}${numbers}`; + + setUsername(randomUsername); + checkUsernameAvailability(randomUsername); } catch (error) { console.error('Error generating username:', error); toast.error('Error generating username'); @@ -223,17 +255,17 @@ export default function CompleteProfile() { } return ( -
-
+
+
{/* Header */}
-
- CU +
+
-

- Welcome! Let's set up your CodeUnia profile. +

+ Welcome! Let's set up your profile

-

+

Complete your profile to get started with CodeUnia. This will only take a moment.

@@ -241,119 +273,171 @@ export default function CompleteProfile() { {/* Setup Form */}
{/* First Name */} -
-