transcriptor-web/resources/js/Pages/Dashboard.tsx
2025-04-05 15:58:14 +02:00

115 lines
4.9 KiB
TypeScript

import React, {useEffect, useState} from 'react';
import axios from 'axios';
import AppLayout from '@/Layouts/AppLayout';
import {Typography} from "@material-tailwind/react";
interface StatsData {
transcription_duration_average: number;
vod_processing_average: number;
clip_average_per_day: number;
video_downloaded_true: number;
video_downloaded_false: number;
processed_video_count: number;
}
const formatDuration = (seconds: number): string => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
const hours = Math.floor(minutes / 60);
const remainingMinutes = minutes % 60;
if (hours >= 1) {
return `${hours}h ${remainingMinutes}m`;
}
return `${minutes}m`;
};
export default function Dashboard() {
const [stats, setStats] = useState<StatsData | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
axios.get('/api/dashboard/stats')
.then(response => {
setStats(response.data);
setLoading(false);
})
.catch(err => {
setError('Failed to load stats.');
setLoading(false);
});
}, []);
return (
<AppLayout
title="Dashboard"
renderHeader={() => (
<h2 className="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
Dashboard
</h2>
)}
>
<div className="py-12">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div className="bg-white dark:bg-gray-800 overflow-hidden shadow-xl sm:rounded-lg p-6">
<Typography className="text-[18px] pb-5 font-bold">
Last 30 days
</Typography>
{loading ? (
<div className="flex justify-center items-center">Loading...</div>
) : error ? (
<div className="text-red-500 text-center">{error}</div>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="card bg-base-100 shadow-md">
<div className="card-body">
<h2 className="card-title">Avg. Transcription Duration</h2>
<p>{formatDuration(stats?.transcription_duration_average ?? 0)}</p>
</div>
</div>
<div className="card bg-base-100 shadow-md">
<div className="card-body">
<h2 className="card-title">VOD processing delay</h2>
<p>{formatDuration(stats?.vod_processing_average ?? 0)}</p>
</div>
</div>
<div className="card bg-base-100 shadow-md">
<div className="card-body">
<h2 className="card-title">Avg. Clips per Day</h2>
<p>{stats?.clip_average_per_day} clips</p>
</div>
</div>
</div>
)}
</div>
<div className="bg-white dark:bg-gray-800 overflow-hidden shadow-xl sm:rounded-lg p-6 mt-2">
<Typography className="text-[18px] pb-5 font-bold">
All time
</Typography>
{loading ? (
<div className="flex justify-center items-center">Loading...</div>
) : error ? (
<div className="text-red-500 text-center">{error}</div>
) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="card bg-base-100 shadow-md">
<div className="card-body">
<h2 className="card-title">VOD stats</h2>
<p>{stats?.video_downloaded_true} downloaded</p>
<p>{stats?.video_downloaded_false} not downloaded</p>
<p>{stats?.processed_video_count} transcripted</p>
</div>
</div>
</div>
)}
</div>
</div>
</div>
</AppLayout>
);
}