app-pro / code.txt
Dooratre's picture
Upload 323 files
4efd266 verified
## πŸ“‹ MESSAGE FOR FRONTEND DEVELOPER
### What changed in the backend:
1. **User data now has a new field: `profile_photo_url`** β€” This is the user's Telegram profile photo URL. It can be `null` if the user has no Telegram profile photo.
2. **New API endpoints available:**
- `GET /api/me/profile` β†’ Returns `{ username, profile_photo_url, student_type, balance, telegram_user_id }`
- `GET /api/user/<username>/profile` β†’ Returns `{ username, profile_photo_url, student_type }` (for other users, used in notifications/sharing)
- `GET /me` (existing, updated) β†’ Now also returns `profile_photo_url` field
3. **Notifications now include `from_profile_photo_url`** β€” When a user shares a board, the notification object sent to the recipient now has a `from_profile_photo_url` field (can be `null`).
4. **Dashboard template now receives `profile_photo_url` variable** β€” Passed from backend as a template variable.
5. **After signup β†’ verification β†’ success, user goes directly to dashboard** (no longer redirected to login page).
---
### Pages that need frontend updates:
#### 1. `templates/dashboard.html`
- **Display user's profile photo** next to their username/greeting area
- Backend passes `profile_photo_url` (can be `null`)
- **Fallback rule:** If `profile_photo_url` is `null` or empty, show a circle with the **first letter of `username`** (uppercase) as the avatar, with a colored background
- Example: User "ahmed" with no photo β†’ show a circle with letter "A"
- The variable is available as `{{ profile_photo_url }}` in Jinja2 and `{{ username }}` for the fallback letter
#### 2. `templates/chat.html`
- **Display user's profile photo as their chat icon** next to their messages
- Fetch profile from `GET /me` endpoint (already called on page load) β€” it now returns `profile_photo_url`
- **Fallback rule:** Same as dashboard β€” if `null`, use first letter of username in a colored circle
- The AI/teacher messages keep their existing icon (no change)
#### 3. **Notifications display** (wherever notifications are rendered β€” likely in `dashboard.html` or a notifications panel)
- Each notification of type `board_share` now has `from_profile_photo_url` field
- Display the **sender's profile photo** next to the notification text
- **Fallback rule:** If `from_profile_photo_url` is `null`, use first letter of `from_username` in a colored circle
- The `from_username` field is already present in notifications
#### 4. **Board share UI** (in `templates/board.html` if there's a share dialog)
- When searching users via `GET /api/users/search`, the results include `username` and `student_type`
- To show profile photos in search results, make an additional call to `GET /api/user/<username>/profile` for each result, OR just use the first-letter fallback (simpler)
---
### Avatar fallback logic (use everywhere):
```javascript
// Helper function for all pages
function getAvatarHTML(profilePhotoUrl, username, size = 40) {
if (profilePhotoUrl) {
return `<img src="${profilePhotoUrl}" alt="${username}"
style="width:${size}px; height:${size}px; border-radius:50%; object-fit:cover;"
onerror="this.outerHTML=getLetterAvatarHTML('${username}', ${size})">`;
}
return getLetterAvatarHTML(username, size);
}
function getLetterAvatarHTML(username, size = 40) {
const letter = (username && username.length > 0) ? username.charAt(0).toUpperCase() : '?';
// Generate consistent color from username
const colors = ['#7C3AED', '#0EA5E9', '#10B981', '#F59E0B', '#EF4444', '#EC4899', '#8B5CF6', '#06B6D4'];
let hash = 0;
for (let i = 0; i < username.length; i++) {
hash = username.charCodeAt(i) + ((hash << 5) - hash);
}
const color = colors[Math.abs(hash) % colors.length];
const fontSize = Math.round(size * 0.45);
return `<div style="width:${size}px; height:${size}px; border-radius:50%;
background:${color}; display:flex; align-items:center; justify-content:center;
color:white; font-weight:700; font-size:${fontSize}px; font-family:'Cairo',sans-serif;
flex-shrink:0;">${letter}</div>`;
}
```
### Jinja2 macro for templates (use in dashboard.html and anywhere server-rendered):
```html
{# Place this at the top of any template that needs avatars #}
{% macro avatar(photo_url, username, size=40) %}
{% if photo_url %}
<img src="{{ photo_url }}" alt="{{ username }}"
style="width:{{ size }}px; height:{{ size }}px; border-radius:50%; object-fit:cover;"
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
<div style="width:{{ size }}px; height:{{ size }}px; border-radius:50%;
background:#7C3AED; display:none; align-items:center; justify-content:center;
color:white; font-weight:700; font-size:{{ (size * 0.45)|int }}px; font-family:'Cairo',sans-serif;">
{{ username[0]|upper if username else '?' }}
</div>
{% else %}
<div style="width:{{ size }}px; height:{{ size }}px; border-radius:50%;
background:#7C3AED; display:flex; align-items:center; justify-content:center;
color:white; font-weight:700; font-size:{{ (size * 0.45)|int }}px; font-family:'Cairo',sans-serif;">
{{ username[0]|upper if username else '?' }}
</div>
{% endif %}
{% endmacro %}
```
### Summary of where to use avatars:
| Page | Where | Data source | Photo field | Username field |
|------|-------|-------------|-------------|----------------|
| `dashboard.html` | User greeting area (top) | Template variable | `{{ profile_photo_url }}` | `{{ username }}` |
| `chat.html` | Next to user's own messages | JS from `GET /me` response | `response.profile_photo_url` | `response.username` |
| `dashboard.html` or notification panel | Each notification item | Notification object | `notif.from_profile_photo_url` | `notif.from_username` |
| `board.html` | Share dialog user search results | Use first-letter fallback | N/A (not fetched) | `result.username` |
### Important notes:
- `profile_photo_url` CAN be `null` β€” always handle the fallback
- The `onerror` handler on `<img>` is important because even if a URL exists, it might be expired or broken (Telegram URLs can expire)
- The `GET /api/user/<username>/profile` endpoint exists if you ever need to fetch another user's photo on demand, but for notifications the `from_profile_photo_url` is already included in the notification data
- No changes needed to `verification.html` β€” it works correctly now
- No changes needed to `signup.html` or `login.html`