Files
devplacepy/devplacepy/templates/profile.html
T
retoor ccb885607a feat: add fast-path early return for empty input in parse function
The parse function now checks for empty input at the top and returns immediately, avoiding unnecessary processing overhead for trivial cases. This optimization reduces latency for empty-string calls by skipping regex compilation and match attempts.
2026-05-11 01:14:43 +00:00

227 lines
12 KiB
HTML

{% extends "base.html" %}
{% block extra_head %}
<link rel="stylesheet" href="/static/css/profile.css">
<link rel="stylesheet" href="/static/css/projects.css">
<style>
.hidden { display: none !important; }
</style>
{% endblock %}
{% block content %}
<div class="profile-layout">
<aside class="profile-sidebar">
<div class="profile-card">
<div class="profile-avatar-wrap">
<img src="{{ avatar_url('multiavatar', profile_user['username'], 80) }}" class="avatar-img avatar-lg" alt="{{ profile_user['username'] }}" id="profile-avatar-preview">
</div>
<div class="profile-name">{{ profile_user['username'] }}</div>
{% if profile_user.get('role') %}
<div class="profile-role">{{ profile_user['role'] }}</div>
{% endif %}
<div class="profile-stats">
<div class="profile-stat">
<span class="profile-stat-value">{{ posts_count }}</span>
<span class="profile-stat-label">Posts</span>
</div>
<div class="profile-stat">
<span class="profile-stat-value">{{ profile_user.get('level', 1) }}</span>
<span class="profile-stat-label">Level</span>
</div>
<div class="profile-stat">
<span class="profile-stat-value">{{ profile_user.get('stars', 0) }}</span>
<span class="profile-stat-label">Stars</span>
</div>
</div>
<div class="profile-level-bar">
<div class="level-label">
<span>Progress to next level</span>
<span>{{ profile_user.get('xp', 0) % 100 }}%</span>
</div>
<div class="bar">
<div class="bar-fill" style="width: {{ profile_user.get('xp', 0) % 100 }}%"></div>
</div>
</div>
<div class="profile-badges">
{% for badge in badges %}
<span class="profile-badge">{{ badge['badge_name'] }}</span>
{% else %}
<span class="profile-badge">Member</span>
{% endfor %}
</div>
</div>
{% if user and user['uid'] != profile_user['uid'] %}
<div style="margin-top: 1rem;">
{% if is_following %}
<form method="POST" action="/follow/unfollow/{{ profile_user['username'] }}">
<button type="submit" class="btn btn-secondary btn-sm" style="width: 100%;">Unfollow</button>
</form>
{% else %}
<form method="POST" action="/follow/{{ profile_user['username'] }}">
<button type="submit" class="btn btn-primary btn-sm" style="width: 100%;">Follow</button>
</form>
{% endif %}
</div>
{% endif %}
{% if user and user['uid'] == profile_user['uid'] %}
<div class="profile-info">
<form method="POST" action="/profile/update">
<div class="profile-info-row">
<span class="profile-info-label">Bio</span>
<div style="display: flex; align-items: center; gap: 0.5rem;">
<span class="profile-info-value bio-display" id="display-bio">{{ profile_user.get('bio', '') or 'Not set' }}</span>
<button type="button" class="profile-info-edit" data-edit-field="bio">&#x270E;</button>
</div>
</div>
<div class="auth-field hidden" id="input-bio" style="margin-bottom: 0.5rem;">
<textarea name="bio" maxlength="500" rows="2" style="font-size: 0.8125rem;">{{ profile_user.get('bio', '') }}</textarea>
</div>
<div class="profile-info-row">
<span class="profile-info-label">Location</span>
<div style="display: flex; align-items: center; gap: 0.5rem;">
<span class="profile-info-value" id="display-location">{{ profile_user.get('location', '') or 'Not set' }}</span>
<button type="button" class="profile-info-edit" data-edit-field="location">&#x270E;</button>
</div>
</div>
<div class="auth-field hidden" id="input-location" style="margin-bottom: 0.5rem;">
<input type="text" name="location" maxlength="200" value="{{ profile_user.get('location', '') }}" style="font-size: 0.8125rem;">
</div>
<div class="profile-info-row">
<span class="profile-info-label">Git Link</span>
<div style="display: flex; align-items: center; gap: 0.5rem;">
<span class="profile-info-value" id="display-git_link">{{ profile_user.get('git_link', '') or 'Not set' }}</span>
<button type="button" class="profile-info-edit" data-edit-field="git_link">&#x270E;</button>
</div>
</div>
<div class="auth-field hidden" id="input-git_link" style="margin-bottom: 0.5rem;">
<input type="url" name="git_link" maxlength="500" value="{{ profile_user.get('git_link', '') }}" style="font-size: 0.8125rem;">
</div>
<div class="profile-info-row">
<span class="profile-info-label">Website</span>
<div style="display: flex; align-items: center; gap: 0.5rem;">
<span class="profile-info-value" id="display-website">{{ profile_user.get('website', '') or 'Not set' }}</span>
<button type="button" class="profile-info-edit" data-edit-field="website">&#x270E;</button>
</div>
</div>
<div class="auth-field hidden" id="input-website" style="margin-bottom: 0.5rem;">
<input type="url" name="website" maxlength="500" value="{{ profile_user.get('website', '') }}" style="font-size: 0.8125rem;">
</div>
<button type="submit" class="btn btn-primary btn-sm" style="width: 100%; margin-top: 0.5rem;">Save Changes</button>
</form>
</div>
{% else %}
<div class="profile-info">
<div class="profile-info-row">
<span class="profile-info-label">Bio</span>
<span class="profile-info-value">{{ profile_user.get('bio', '') or 'Not set' }}</span>
</div>
<div class="profile-info-row">
<span class="profile-info-label">Location</span>
<span class="profile-info-value">{{ profile_user.get('location', '') or 'Not set' }}</span>
</div>
<div class="profile-info-row">
<span class="profile-info-label">Git Link</span>
<span class="profile-info-value">{{ profile_user.get('git_link', '') or 'Not set' }}</span>
</div>
<div class="profile-info-row">
<span class="profile-info-label">Website</span>
<span class="profile-info-value">{{ profile_user.get('website', '') or 'Not set' }}</span>
</div>
</div>
{% endif %}
</aside>
<div class="profile-content">
<a href="/feed" style="display: inline-flex; align-items: center; gap: 0.375rem; color: var(--text-secondary); font-size: 0.875rem; margin-bottom: 1rem;">&larr; Back</a>
<div class="profile-tabs">
<a href="/profile/{{ profile_user['username'] }}?tab=posts" class="profile-tab {% if current_tab == 'posts' %}active{% endif %}">Posts</a>
<a href="/profile/{{ profile_user['username'] }}?tab=projects" class="profile-tab {% if current_tab == 'projects' %}active{% endif %}">Projects</a>
<a href="/profile/{{ profile_user['username'] }}?tab=activity" class="profile-tab {% if current_tab == 'activity' %}active{% endif %}">Activity</a>
<button class="btn-ghost btn-icon" style="margin-left: auto; font-size: 0.8125rem;">&#x25B3;</button>
</div>
<div class="profile-posts">
{% if current_tab == 'posts' %}
{% for item in posts %}
<article class="post-card fade-in">
<div class="post-header">
<img src="{{ avatar_url('multiavatar', profile_user['username'], 32) }}" class="avatar-img avatar-sm" alt="{{ profile_user['username'] }}">
<div class="post-author-wrap">
<span class="post-author">{{ profile_user['username'] }}</span>
{% if profile_user.get('role') %}
<span class="post-author-role">{{ profile_user['role'] }}</span>
{% endif %}
</div>
<span class="post-time">{{ item.time_ago }}</span>
</div>
<div class="post-topic">
<span class="badge badge-{{ item.post['topic'] }}">{{ item.post['topic'] }}</span>
</div>
{% if item.post.get('title') %}
<h3 class="post-title">{{ item.post['title'] }}</h3>
{% endif %}
<p class="post-content">{{ item.post['content'][:200] }}{% if item.post['content']|length > 200 %}...{% endif %}</p>
<div class="post-actions">
<span class="post-action-btn" style="cursor: default;">+{{ item.post.get('stars', 0) }}</span>
<span class="post-action-btn" style="cursor: default;">&#x1F4AC; {{ item.comment_count }}</span>
<a href="/posts/{{ item.post['uid'] }}" class="post-action-btn share">&#x2197;&#xFE0E; Open</a>
</div>
</article>
{% else %}
<div class="empty-state">No posts yet.</div>
{% endfor %}
{% elif current_tab == 'projects' %}
{% for p in projects %}
<div class="project-card fade-in">
<div class="project-card-header">
<h3 class="project-card-title">{{ p['title'] }}</h3>
</div>
<div class="project-card-meta">
<span class="project-status {% if p.get('status') == 'Released' %}released{% else %}dev{% endif %}">
&#x25CF; {{ p.get('status', 'In Development') }}
</span>
<span>{{ p.get('project_type', 'software')|replace('_', ' ')|capitalize }}</span>
</div>
<div class="project-card-desc">{{ p.get('description', '')[:200] }}</div>
{% if p.get('platforms') %}
<div class="project-card-platforms">
{% for plat in p['platforms'].split(',') %}
<span class="platform-tag">{{ plat.strip() }}</span>
{% endfor %}
</div>
{% endif %}
</div>
{% else %}
<div class="empty-state">No projects yet.</div>
{% endfor %}
{% else %}
{% for act in activities %}
<div class="post-card fade-in" style="padding: 0.75rem 1rem;">
<div style="display: flex; align-items: center; gap: 0.5rem; font-size: 0.8125rem;">
<span style="color: var(--text-muted);">
{% if act['type'] == 'post' %}&#x1F4DD;{% else %}&#x1F4AC;{% endif %}
</span>
<span style="color: var(--text-secondary);">
{% if act['type'] == 'post' %}Posted{% else %}Commented{% endif %}
</span>
<span style="color: var(--text-muted);">{{ act['time_ago'] }}</span>
</div>
<p style="font-size: 0.8125rem; color: var(--text-muted); margin-top: 0.25rem;">{{ act['content'] }}</p>
</div>
{% else %}
<div class="empty-state">No activity yet.</div>
{% endfor %}
{% endif %}
</div>
</div>
</div>
{% endblock %}