Commit a025a15f authored by shaw's avatar shaw
Browse files

feat: add refresh button to admin and user dashboard pages

parent 318aa5e0
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">{{ t('dashboard.timeRange') }}:</span> <span class="text-sm font-medium text-gray-700 dark:text-gray-300">{{ t('dashboard.timeRange') }}:</span>
<DateRangePicker :start-date="startDate" :end-date="endDate" @update:startDate="$emit('update:startDate', $event)" @update:endDate="$emit('update:endDate', $event)" @change="$emit('dateRangeChange', $event)" /> <DateRangePicker :start-date="startDate" :end-date="endDate" @update:startDate="$emit('update:startDate', $event)" @update:endDate="$emit('update:endDate', $event)" @change="$emit('dateRangeChange', $event)" />
</div> </div>
<button @click="$emit('refresh')" :disabled="loading" class="btn btn-secondary">
{{ t('common.refresh') }}
</button>
<div class="ml-auto flex items-center gap-2"> <div class="ml-auto flex items-center gap-2">
<span class="text-sm font-medium text-gray-700 dark:text-gray-300">{{ t('dashboard.granularity') }}:</span> <span class="text-sm font-medium text-gray-700 dark:text-gray-300">{{ t('dashboard.granularity') }}:</span>
<div class="w-28"> <div class="w-28">
...@@ -74,7 +77,7 @@ import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement ...@@ -74,7 +77,7 @@ import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, ArcElement, Title, Tooltip, Legend, Filler) ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, ArcElement, Title, Tooltip, Legend, Filler)
const props = defineProps<{ loading: boolean, startDate: string, endDate: string, granularity: string, trend: TrendDataPoint[], models: ModelStat[] }>() const props = defineProps<{ loading: boolean, startDate: string, endDate: string, granularity: string, trend: TrendDataPoint[], models: ModelStat[] }>()
defineEmits(['update:startDate', 'update:endDate', 'update:granularity', 'dateRangeChange', 'granularityChange']) defineEmits(['update:startDate', 'update:endDate', 'update:granularity', 'dateRangeChange', 'granularityChange', 'refresh'])
const { t } = useI18n() const { t } = useI18n()
const modelData = computed(() => !props.models?.length ? null : { const modelData = computed(() => !props.models?.length ? null : {
......
...@@ -219,6 +219,9 @@ ...@@ -219,6 +219,9 @@
@change="onDateRangeChange" @change="onDateRangeChange"
/> />
</div> </div>
<button @click="loadDashboardStats" :disabled="chartsLoading" class="btn btn-secondary">
{{ t('common.refresh') }}
</button>
<div class="ml-auto flex items-center gap-2"> <div class="ml-auto flex items-center gap-2">
<span class="text-sm font-medium text-gray-700 dark:text-gray-300" <span class="text-sm font-medium text-gray-700 dark:text-gray-300"
>{{ t('admin.dashboard.granularity') }}:</span >{{ t('admin.dashboard.granularity') }}:</span
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<div v-if="loading" class="flex items-center justify-center py-12"><LoadingSpinner /></div> <div v-if="loading" class="flex items-center justify-center py-12"><LoadingSpinner /></div>
<template v-else-if="stats"> <template v-else-if="stats">
<UserDashboardStats :stats="stats" :balance="user?.balance || 0" :is-simple="authStore.isSimpleMode" /> <UserDashboardStats :stats="stats" :balance="user?.balance || 0" :is-simple="authStore.isSimpleMode" />
<UserDashboardCharts v-model:startDate="startDate" v-model:endDate="endDate" v-model:granularity="granularity" :loading="loadingCharts" :trend="trendData" :models="modelStats" @dateRangeChange="loadCharts" @granularityChange="loadCharts" /> <UserDashboardCharts v-model:startDate="startDate" v-model:endDate="endDate" v-model:granularity="granularity" :loading="loadingCharts" :trend="trendData" :models="modelStats" @dateRangeChange="loadCharts" @granularityChange="loadCharts" @refresh="refreshAll" />
<div class="grid grid-cols-1 gap-6 lg:grid-cols-3"> <div class="grid grid-cols-1 gap-6 lg:grid-cols-3">
<div class="lg:col-span-2"><UserDashboardRecentUsage :data="recentUsage" :loading="loadingUsage" /></div> <div class="lg:col-span-2"><UserDashboardRecentUsage :data="recentUsage" :loading="loadingUsage" /></div>
<div class="lg:col-span-1"><UserDashboardQuickActions /></div> <div class="lg:col-span-1"><UserDashboardQuickActions /></div>
...@@ -31,6 +31,7 @@ const startDate = ref(formatLD(new Date(Date.now() - 6 * 86400000))); const endD ...@@ -31,6 +31,7 @@ const startDate = ref(formatLD(new Date(Date.now() - 6 * 86400000))); const endD
const loadStats = async () => { loading.value = true; try { await authStore.refreshUser(); stats.value = await usageAPI.getDashboardStats() } catch (error) { console.error('Failed to load dashboard stats:', error) } finally { loading.value = false } } const loadStats = async () => { loading.value = true; try { await authStore.refreshUser(); stats.value = await usageAPI.getDashboardStats() } catch (error) { console.error('Failed to load dashboard stats:', error) } finally { loading.value = false } }
const loadCharts = async () => { loadingCharts.value = true; try { const res = await Promise.all([usageAPI.getDashboardTrend({ start_date: startDate.value, end_date: endDate.value, granularity: granularity.value as any }), usageAPI.getDashboardModels({ start_date: startDate.value, end_date: endDate.value })]); trendData.value = res[0].trend || []; modelStats.value = res[1].models || [] } catch (error) { console.error('Failed to load charts:', error) } finally { loadingCharts.value = false } } const loadCharts = async () => { loadingCharts.value = true; try { const res = await Promise.all([usageAPI.getDashboardTrend({ start_date: startDate.value, end_date: endDate.value, granularity: granularity.value as any }), usageAPI.getDashboardModels({ start_date: startDate.value, end_date: endDate.value })]); trendData.value = res[0].trend || []; modelStats.value = res[1].models || [] } catch (error) { console.error('Failed to load charts:', error) } finally { loadingCharts.value = false } }
const loadRecent = async () => { loadingUsage.value = true; try { const res = await usageAPI.getByDateRange(startDate.value, endDate.value); recentUsage.value = res.items.slice(0, 5) } catch (error) { console.error('Failed to load recent usage:', error) } finally { loadingUsage.value = false } } const loadRecent = async () => { loadingUsage.value = true; try { const res = await usageAPI.getByDateRange(startDate.value, endDate.value); recentUsage.value = res.items.slice(0, 5) } catch (error) { console.error('Failed to load recent usage:', error) } finally { loadingUsage.value = false } }
const refreshAll = () => { loadStats(); loadCharts(); loadRecent() }
onMounted(() => { loadStats(); loadCharts(); loadRecent() }) onMounted(() => { refreshAll() })
</script> </script>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment