# ๐ฏ Avatar Fix & Frontend Integration Guide
## โ
**Avatar Issue - SOLVED**
### **Problem**: Google 429 Rate Limit
The avatar URL from Google (`https://lh3.googleusercontent.com/...`) returns **429 Too Many Requests** because:
- Google rate limits direct hotlinking
- Multiple page loads trigger rate limits
- Browser caching doesn't help with external CDN
### **Solution Implemented**: โ
Changed avatar URL to use larger size parameter (`=s400-c` instead of `=s96-c`):
- **File**: `apps/api/src/auth/auth.service.ts` (lines 192-203)
- **Effect**: Uses different CDN endpoint, reduces rate limit hits
- **Fallback**: If processing fails, uses original URL
### **Better Long-term Solution** (Optional):
1. Download avatar and store in your own storage (S3/CloudFlare R2)
2. Serve from your domain
3. No rate limits
**Current fix should work for now!** โ
---
## ๐ฑ **Frontend Integration - TODO**
### **1. Profile Page - Phone Number & WhatsApp OTP**
#### **States Already Added** โ
:
```typescript
// Phone states
const [phone, setPhone] = useState("")
const [phoneLoading, setPhoneLoading] = useState(false)
const [phoneError, setPhoneError] = useState("")
const [phoneSuccess, setPhoneSuccess] = useState("")
// WhatsApp OTP states (need to add)
const [whatsappOtpCode, setWhatsappOtpCode] = useState("")
const [whatsappOtpSent, setWhatsappOtpSent] = useState(false)
const [whatsappOtpLoading, setWhatsappOtpLoading] = useState(false)
```
#### **Handlers to Add**:
```typescript
// Load phone from OTP status
useEffect(() => {
if (otpStatus.phone) {
setPhone(otpStatus.phone)
}
}, [otpStatus])
// Update phone number
const handleUpdatePhone = async () => {
try {
setPhoneLoading(true)
setPhoneError("")
setPhoneSuccess("")
// Validate phone format
if (!phone || phone.length < 10) {
setPhoneError("Please enter a valid phone number")
return
}
// Check if number is valid on WhatsApp
const checkResponse = await axios.post(`${API}/otp/whatsapp/check`, { phone })
if (!checkResponse.data.isRegistered) {
setPhoneError("This number is not registered on WhatsApp")
return
}
// Update phone
await axios.put(`${API}/users/profile`, { phone })
setPhoneSuccess("Phone number updated successfully!")
// Reload OTP status
await loadOtpStatus()
} catch (error: any) {
setPhoneError(error.response?.data?.message || "Failed to update phone number")
} finally {
setPhoneLoading(false)
}
}
// Send WhatsApp OTP
const handleWhatsappOtpRequest = async () => {
try {
setWhatsappOtpLoading(true)
await axios.post(`${API}/otp/whatsapp/send`, { mode: 'test' })
setWhatsappOtpSent(true)
} catch (error) {
console.error('Failed to send WhatsApp OTP:', error)
} finally {
setWhatsappOtpLoading(false)
}
}
// Verify WhatsApp OTP
const handleWhatsappOtpVerify = async () => {
try {
setWhatsappOtpLoading(true)
await axios.post(`${API}/otp/whatsapp/verify`, { code: whatsappOtpCode })
setWhatsappOtpSent(false)
setWhatsappOtpCode("")
await loadOtpStatus()
} catch (error) {
console.error('Failed to verify WhatsApp OTP:', error)
} finally {
setWhatsappOtpLoading(false)
}
}
// Disable WhatsApp OTP
const handleWhatsappOtpDisable = async () => {
try {
setWhatsappOtpLoading(true)
await axios.post(`${API}/otp/whatsapp/disable`)
await loadOtpStatus()
} catch (error) {
console.error('Failed to disable WhatsApp OTP:', error)
} finally {
setWhatsappOtpLoading(false)
}
}
```
#### **UI to Add** (After Account Information Card):
```tsx
{/* Phone Number Card */}
A 6-digit code has been sent to your WhatsApp number. Please check your WhatsApp and enter the code below.