feat: Expose level progress percentage in profile API response #144
@@ -46,6 +46,7 @@ from devplacepy.utils import (
|
|||||||
track_action,
|
track_action,
|
||||||
build_achievements,
|
build_achievements,
|
||||||
)
|
)
|
||||||
|
from devplacepy.utils.rewards import LEVEL_XP
|
||||||
from devplacepy.responses import respond, action_result, wants_json
|
from devplacepy.responses import respond, action_result, wants_json
|
||||||
from devplacepy.schemas import ProfileOut
|
from devplacepy.schemas import ProfileOut
|
||||||
from devplacepy.avatar import avatar_url, avatar_seed
|
from devplacepy.avatar import avatar_url, avatar_seed
|
||||||
@@ -139,6 +140,10 @@ async def profile_page(
|
|||||||
current_user["uid"], f"/profile/{profile_user['username']}"
|
current_user["uid"], f"/profile/{profile_user['username']}"
|
||||||
)
|
)
|
||||||
profile_user["stars"] = get_user_stars(profile_user["uid"])
|
profile_user["stars"] = get_user_stars(profile_user["uid"])
|
||||||
|
xp_raw = profile_user.get("xp") or 0
|
||||||
|
level_raw = profile_user.get("level") or 1
|
||||||
|
xp_progress_pct = xp_raw % LEVEL_XP
|
||||||
|
xp_next_level = level_raw * LEVEL_XP
|
||||||
rank = get_user_rank(profile_user["uid"])
|
rank = get_user_rank(profile_user["uid"])
|
||||||
follow_counts = get_follow_counts(profile_user["uid"])
|
follow_counts = get_follow_counts(profile_user["uid"])
|
||||||
|
|
||||||
@@ -440,6 +445,8 @@ async def profile_page(
|
|||||||
"awards_count": awards_count,
|
"awards_count": awards_count,
|
||||||
"prominent_award": prominent_award,
|
"prominent_award": prominent_award,
|
||||||
"can_give_award": can_give,
|
"can_give_award": can_give,
|
||||||
|
"xp_next_level": xp_next_level,
|
||||||
|
"xp_progress_pct": xp_progress_pct,
|
||||||
},
|
},
|
||||||
model=ProfileOut,
|
model=ProfileOut,
|
||||||
)
|
)
|
||||||
@@ -499,3 +506,7 @@ async def regenerate_api_key(request: Request):
|
|||||||
links=[audit.target("user", user["uid"], user["username"])],
|
links=[audit.target("user", user["uid"], user["username"])],
|
||||||
)
|
)
|
||||||
return JSONResponse({"api_key": new_key})
|
return JSONResponse({"api_key": new_key})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ class UserOut(_Out):
|
|||||||
website: Optional[str] = None
|
website: Optional[str] = None
|
||||||
level: Optional[int] = None
|
level: Optional[int] = None
|
||||||
xp: Optional[int] = None
|
xp: Optional[int] = None
|
||||||
|
xp_progress_pct: Optional[int] = None
|
||||||
|
xp_next_level: Optional[int] = None
|
||||||
stars: Optional[int] = None
|
stars: Optional[int] = None
|
||||||
created_at: Optional[str] = None
|
created_at: Optional[str] = None
|
||||||
last_seen: Optional[str] = None
|
last_seen: Optional[str] = None
|
||||||
@@ -202,3 +204,4 @@ class MessageOut(_Out):
|
|||||||
|
|
||||||
|
|
||||||
CommentItemOut.model_rebuild()
|
CommentItemOut.model_rebuild()
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ class ProfileOut(_Out):
|
|||||||
followers_count: Optional[int] = None
|
followers_count: Optional[int] = None
|
||||||
following_count: Optional[int] = None
|
following_count: Optional[int] = None
|
||||||
viewer_is_admin: bool = False
|
viewer_is_admin: bool = False
|
||||||
|
xp_next_level: int = 0
|
||||||
|
xp_progress_pct: int = 0
|
||||||
media: list[MediaItemOut] = []
|
media: list[MediaItemOut] = []
|
||||||
media_pagination: Optional[Any] = None
|
media_pagination: Optional[Any] = None
|
||||||
notification_prefs: list[Any] = []
|
notification_prefs: list[Any] = []
|
||||||
@@ -88,3 +90,4 @@ class TelegramPairOut(_Out):
|
|||||||
code: Optional[str] = None
|
code: Optional[str] = None
|
||||||
expires_at: Optional[str] = None
|
expires_at: Optional[str] = None
|
||||||
ttl_minutes: Optional[int] = None
|
ttl_minutes: Optional[int] = None
|
||||||
|
|
||||||
|
|||||||
@@ -42,10 +42,10 @@
|
|||||||
<div class="profile-level-bar">
|
<div class="profile-level-bar">
|
||||||
<div class="level-label">
|
<div class="level-label">
|
||||||
<span>Progress to next level</span>
|
<span>Progress to next level</span>
|
||||||
<span>{{ (profile_user.get('xp') or 0) % 100 }}%</span>
|
<span>{{ xp_progress_pct }}%</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="bar">
|
<div class="bar">
|
||||||
<div class="bar-fill" style="--bar-pct: {{ (profile_user.get('xp') or 0) % 100 }}%;"></div>
|
<div class="bar-fill" style="--bar-pct: {{ xp_progress_pct }}%;"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -765,3 +765,6 @@ import { AwardGiver } from "{{ static_url('/static/js/AwardGiver.js') }}";
|
|||||||
new AwardGiver();
|
new AwardGiver();
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user