feat: Update admin dashboard to show registered user count and set default date range for NASA data download to current month
parent
539a5319e4
commit
a10d0e49fe
|
|
@ -1,14 +1,14 @@
|
|||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import selectinload
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy import select, func
|
||||
from typing import List
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.database import get_db
|
||||
from app.models.db import User
|
||||
from app.services.auth import hash_password
|
||||
from app.services.auth_deps import get_current_user # To protect endpoints
|
||||
from app.services.auth_deps import get_current_user, get_current_admin_user # To protect endpoints
|
||||
|
||||
router = APIRouter(prefix="/users", tags=["users"])
|
||||
|
||||
|
|
@ -105,3 +105,16 @@ async def reset_user_password(
|
|||
await db.commit()
|
||||
|
||||
return {"message": f"Password for user {user.username} has been reset."}
|
||||
|
||||
@router.get("/count", response_model=dict)
|
||||
async def get_user_count(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_admin_user: User = Depends(get_current_admin_user) # Ensure only admin can access
|
||||
):
|
||||
"""
|
||||
Get the total count of registered users.
|
||||
"""
|
||||
result = await db.execute(select(func.count(User.id)))
|
||||
total_users = result.scalar_one()
|
||||
return {"total_users": total_users}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,33 @@
|
|||
/**
|
||||
* Dashboard Page
|
||||
*/
|
||||
import { Card, Row, Col, Statistic } from 'antd';
|
||||
import { DatabaseOutlined, GlobalOutlined, RocketOutlined } from '@ant-design/icons';
|
||||
import { Card, Row, Col, Statistic, message } from 'antd';
|
||||
import { GlobalOutlined, RocketOutlined, UserOutlined } from '@ant-design/icons';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { request } from '../../utils/request';
|
||||
|
||||
export function Dashboard() {
|
||||
const [totalUsers, setTotalUsers] = useState<number | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchUserCount = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
// Assuming '/users/count' is the new endpoint we just created in the backend
|
||||
const response = await request.get('/users/count');
|
||||
setTotalUsers(response.data.total_users);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch user count:', error);
|
||||
message.error('无法获取用户总数');
|
||||
setTotalUsers(0); // Set to 0 or handle error display
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
fetchUserCount();
|
||||
}, []); // Run once on mount
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>控制台</h1>
|
||||
|
|
@ -13,7 +36,7 @@ export function Dashboard() {
|
|||
<Card>
|
||||
<Statistic
|
||||
title="天体总数"
|
||||
value={18}
|
||||
value={18} // Currently hardcoded
|
||||
prefix={<GlobalOutlined />}
|
||||
/>
|
||||
</Card>
|
||||
|
|
@ -22,7 +45,7 @@ export function Dashboard() {
|
|||
<Card>
|
||||
<Statistic
|
||||
title="探测器"
|
||||
value={7}
|
||||
value={7} // Currently hardcoded
|
||||
prefix={<RocketOutlined />}
|
||||
/>
|
||||
</Card>
|
||||
|
|
@ -30,13 +53,14 @@ export function Dashboard() {
|
|||
<Col span={8}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="数据记录"
|
||||
value={1245}
|
||||
prefix={<DatabaseOutlined />}
|
||||
title="注册用户数"
|
||||
value={totalUsers !== null ? totalUsers : '-'}
|
||||
loading={loading}
|
||||
prefix={<UserOutlined />}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -56,8 +56,8 @@ export function NASADownload() {
|
|||
const [bodies, setBodies] = useState<GroupedBodies>({});
|
||||
const [selectedBodies, setSelectedBodies] = useState<string[]>([]);
|
||||
const [dateRange, setDateRange] = useState<[Dayjs, Dayjs]>([
|
||||
dayjs().subtract(1, 'month').startOf('month'),
|
||||
dayjs().subtract(1, 'month').endOf('month')
|
||||
dayjs().startOf('month'),
|
||||
dayjs().endOf('month')
|
||||
]);
|
||||
const [availableDates, setAvailableDates] = useState<Set<string>>(new Set());
|
||||
const [loadingDates, setLoadingDates] = useState(false);
|
||||
|
|
|
|||
Loading…
Reference in New Issue