Add registration_activity chart and enhance admin statistics

- Introduced `RegistrationActivityChart` to display user registration trends over 14 days.
- Enhanced `AdminStatsResponse` with `registration_activity`, providing improved insights for admin users.
- Updated demo data to include realistic registration activity and organization details.
- Refactored admin page to use updated statistics data model and improved query handling.
- Fixed inconsistent timezone handling in statistical analytics and demo user timestamps.
This commit is contained in:
Felipe Cardoso
2025-11-24 17:42:43 +01:00
parent 9f655913b1
commit a05def5906
9 changed files with 664 additions and 226 deletions

View File

@@ -9,7 +9,7 @@ import asyncio
import json
import logging
import random
from datetime import datetime, timedelta
from datetime import UTC, datetime, timedelta
from pathlib import Path
from sqlalchemy import select, text
@@ -153,23 +153,24 @@ async def load_demo_data(session):
# Randomize created_at for demo data (last 30 days)
# This makes the charts look more realistic
days_ago = random.randint(0, 30) # noqa: S311
random_time = datetime.utcnow() - timedelta(days=days_ago)
random_time = datetime.now(UTC) - timedelta(days=days_ago)
# Add some random hours/minutes variation
random_time = random_time.replace(
hour=random.randint(0, 23), # noqa: S311
minute=random.randint(0, 59), # noqa: S311
)
# Update the timestamp directly in the database
# Update the timestamp and is_active directly in the database
# We do this to ensure the values are persisted correctly
await session.execute(
text(
"UPDATE users SET created_at = :created_at WHERE id = :user_id"
"UPDATE users SET created_at = :created_at, is_active = :is_active WHERE id = :user_id"
),
{"created_at": random_time, "user_id": user.id},
{"created_at": random_time, "is_active": user_data.get("is_active", True), "user_id": user.id},
)
logger.info(
f"Created demo user: {user.email} (created {days_ago} days ago)"
f"Created demo user: {user.email} (created {days_ago} days ago, active={user_data.get('is_active', True)})"
)
# Add to organization if specified