|
400 | 400 | <br> |
401 | 401 | <h2>User Metrics History</h2> |
402 | 402 | <div class="text-caption mb-4">Trends across stored 28-day snapshots</div> |
403 | | - <Line :data="historyChartData" :options="historyChartOptions" /> |
| 403 | + <div style="height: 320px; position: relative;"> |
| 404 | + <Line :data="historyChartData" :options="historyChartOptions" /> |
| 405 | + </div> |
404 | 406 | <br> |
405 | 407 | <v-data-table |
406 | 408 | :headers="historyHeaders" |
@@ -952,33 +954,67 @@ export default defineComponent({ |
952 | 954 | label: 'Total Users', |
953 | 955 | data: props.userMetricsHistory.map(e => e.total_users), |
954 | 956 | borderColor: 'rgba(63, 81, 181, 1)', |
955 | | - backgroundColor: 'rgba(63, 81, 181, 0.15)', |
| 957 | + backgroundColor: 'rgba(63, 81, 181, 0.08)', |
956 | 958 | fill: true, |
957 | 959 | tension: 0.3, |
| 960 | + pointRadius: 4, |
| 961 | + pointHoverRadius: 6, |
958 | 962 | yAxisID: 'yUsers', |
959 | 963 | }, |
960 | 964 | { |
961 | 965 | label: 'Active Users (≥7 days)', |
962 | 966 | data: props.userMetricsHistory.map(e => e.active_users), |
963 | 967 | borderColor: 'rgba(76, 175, 80, 1)', |
964 | | - backgroundColor: 'rgba(76, 175, 80, 0.1)', |
| 968 | + backgroundColor: 'rgba(76, 175, 80, 0)', |
965 | 969 | fill: false, |
966 | 970 | tension: 0.3, |
| 971 | + pointRadius: 4, |
| 972 | + pointHoverRadius: 6, |
| 973 | + borderDash: [5, 3], |
967 | 974 | yAxisID: 'yUsers', |
968 | 975 | }, |
| 976 | + { |
| 977 | + label: 'Avg Acceptance Rate %', |
| 978 | + data: props.userMetricsHistory.map(e => e.avg_acceptance_rate), |
| 979 | + borderColor: 'rgba(255, 167, 38, 1)', |
| 980 | + backgroundColor: 'rgba(255, 167, 38, 0)', |
| 981 | + fill: false, |
| 982 | + tension: 0.3, |
| 983 | + pointRadius: 4, |
| 984 | + pointHoverRadius: 6, |
| 985 | + yAxisID: 'yRate', |
| 986 | + }, |
969 | 987 | ]; |
970 | 988 | return { labels: props.userMetricsHistory.map(e => e.report_end_day), datasets }; |
971 | 989 | }); |
972 | 990 |
|
973 | 991 | const historyChartOptions = computed(() => { |
974 | | - const scales: Record<string, object> = { |
975 | | - yUsers: { type: 'linear' as const, position: 'left' as const, beginAtZero: true, title: { display: true, text: 'Users' } }, |
976 | | - }; |
| 992 | + const allUsers = props.userMetricsHistory.flatMap(e => [e.total_users, e.active_users]).filter(v => v > 0); |
| 993 | + const minUsers = allUsers.length ? Math.max(0, Math.floor(Math.min(...allUsers) * 0.85)) : 0; |
977 | 994 | return { |
978 | 995 | responsive: true, |
979 | | - maintainAspectRatio: true, |
980 | | - layout: { padding: { left: 60, right: 60, top: 20, bottom: 40 } }, |
981 | | - scales, |
| 996 | + maintainAspectRatio: false, |
| 997 | + plugins: { |
| 998 | + legend: { position: 'top' as const }, |
| 999 | + tooltip: { mode: 'index' as const, intersect: false }, |
| 1000 | + }, |
| 1001 | + scales: { |
| 1002 | + yUsers: { |
| 1003 | + type: 'linear' as const, |
| 1004 | + position: 'left' as const, |
| 1005 | + min: minUsers, |
| 1006 | + title: { display: true, text: 'Users' }, |
| 1007 | + grid: { color: 'rgba(128,128,128,0.15)' }, |
| 1008 | + }, |
| 1009 | + yRate: { |
| 1010 | + type: 'linear' as const, |
| 1011 | + position: 'right' as const, |
| 1012 | + min: 0, |
| 1013 | + max: 110, |
| 1014 | + title: { display: true, text: 'Acceptance %' }, |
| 1015 | + grid: { drawOnChartArea: false }, |
| 1016 | + }, |
| 1017 | + }, |
982 | 1018 | }; |
983 | 1019 | }); |
984 | 1020 |
|
|
0 commit comments