import { AppSidebar } from "@/components/app-sidebar"; import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumb"; import { Separator } from "@/components/ui/separator"; import { SidebarInset, SidebarProvider, SidebarTrigger, } from "@/components/ui/sidebar"; import axios from "axios"; import { Card, CardHeader } from "@/components/ui/card"; import * as Tooltip from "@radix-ui/react-tooltip"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Pagination, PaginationContent, PaginationItem, PaginationPrevious, PaginationNext, PaginationLink, } from "@/components/ui/pagination"; import { useState, useEffect, useRef } from "react"; import Cookies from "js-cookie"; import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; import { toast } from "sonner"; import { Toaster } from "@/components/ui/sonner"; import { useTranslations } from "next-intl"; const timeFormats = { 1: (timestamp: string) => new Date(timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false }), 2: (timestamp: string) => new Date(timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false }), 3: (timestamp: string) => new Date(timestamp).toLocaleDateString([], { day: '2-digit', month: 'short' }), 4: (timestamp: string) => new Date(timestamp).toLocaleDateString([], { day: '2-digit', month: 'short' }) }; const minBoxWidths = { 1: 20, 2: 20, 3: 24, 4: 24 }; interface UptimeData { appName: string; appId: number; uptimeSummary: { timestamp: string; missing: boolean; online: boolean | null; }[]; } interface PaginationData { currentPage: number; totalPages: number; totalItems: number; } export default function Uptime() { const t = useTranslations(); const [data, setData] = useState([]); const [timespan, setTimespan] = useState<1 | 2 | 3 | 4>(1); const [pagination, setPagination] = useState({ currentPage: 1, totalPages: 1, totalItems: 0 }); const [isLoading, setIsLoading] = useState(false); const savedItemsPerPage = Cookies.get("itemsPerPage-uptime"); const defaultItemsPerPage = 5; const initialItemsPerPage = savedItemsPerPage ? parseInt(savedItemsPerPage) : defaultItemsPerPage; const [itemsPerPage, setItemsPerPage] = useState(initialItemsPerPage); const customInputRef = useRef(null); const debounceTimerRef = useRef(null); const getData = async (selectedTimespan: number, page: number, itemsPerPage: number) => { setIsLoading(true); try { const response = await axios.post<{ data: UptimeData[]; pagination: PaginationData; }>("/api/applications/uptime", { timespan: selectedTimespan, page, itemsPerPage }); setData(response.data.data); setPagination(response.data.pagination); } catch (error) { console.error("Error:", error); setData([]); setPagination({ currentPage: 1, totalPages: 1, totalItems: 0 }); } finally { setIsLoading(false); } }; const handlePrevious = () => { const newPage = Math.max(1, pagination.currentPage - 1); setPagination(prev => ({...prev, currentPage: newPage})); getData(timespan, newPage, itemsPerPage); }; const handleNext = () => { const newPage = Math.min(pagination.totalPages, pagination.currentPage + 1); setPagination(prev => ({...prev, currentPage: newPage})); getData(timespan, newPage, itemsPerPage); }; const handleItemsPerPageChange = (value: string) => { if (debounceTimerRef.current) { clearTimeout(debounceTimerRef.current); } debounceTimerRef.current = setTimeout(() => { const newItemsPerPage = parseInt(value); if (isNaN(newItemsPerPage) || newItemsPerPage < 1) { toast.error(t('Uptime.Messages.NumberValidation')); return; } const validatedValue = Math.min(Math.max(newItemsPerPage, 1), 100); setItemsPerPage(validatedValue); setPagination(prev => ({...prev, currentPage: 1})); Cookies.set("itemsPerPage-uptime", String(validatedValue), { expires: 365, path: "/", sameSite: "strict", }); getData(timespan, 1, validatedValue); }, 300); }; useEffect(() => { getData(timespan, 1, itemsPerPage); }, [timespan]); return (
/ {t('Uptime.Breadcrumb.MyInfrastructure')} {t('Uptime.Breadcrumb.Uptime')}
{t('Uptime.Title')}
{ const value = parseInt(e.target.value); if (isNaN(value) || value < 1 || value > 100) { e.target.classList.add("border-red-500"); } else { e.target.classList.remove("border-red-500"); } }} onBlur={(e) => { const value = parseInt(e.target.value); if (value >= 1 && value <= 100) { handleItemsPerPageChange(e.target.value); } }} onKeyDown={(e) => { if (e.key === 'Enter') { if (debounceTimerRef.current) { clearTimeout(debounceTimerRef.current); debounceTimerRef.current = null; } const value = parseInt((e.target as HTMLInputElement).value); if (value >= 1 && value <= 100) { const validatedValue = Math.min(Math.max(value, 1), 100); setItemsPerPage(validatedValue); setPagination(prev => ({...prev, currentPage: 1})); Cookies.set("itemsPerPage-uptime", String(validatedValue), { expires: 365, path: "/", sameSite: "strict", }); getData(timespan, 1, validatedValue); document.body.click(); } } }} onClick={(e) => e.stopPropagation()} /> {t('Common.ItemsPerPage.items')}
{isLoading ? (
{t('Uptime.Messages.Loading')}
) : ( data.map((app) => { const reversedSummary = [...app.uptimeSummary].reverse(); const startTime = reversedSummary[0]?.timestamp; const endTime = reversedSummary[reversedSummary.length - 1]?.timestamp; return (
{app.appName}
{startTime ? timeFormats[timespan](startTime) : ""} {endTime ? timeFormats[timespan](endTime) : ""}
{reversedSummary.map((entry) => (

{new Date(entry.timestamp).toLocaleString([], { year: 'numeric', month: 'short', day: timespan > 2 ? 'numeric' : undefined, hour: '2-digit', minute: timespan === 1 ? '2-digit' : undefined, hour12: false })}

{entry.missing ? t('Uptime.Status.NoData') : entry.online ? t('Uptime.Status.Online') : t('Uptime.Status.Offline')}

))}
); }) )}
{pagination.totalItems > 0 && !isLoading && (
{pagination.totalItems > 0 ? t('Uptime.Pagination.Showing', { start: ((pagination.currentPage - 1) * itemsPerPage) + 1, end: Math.min(pagination.currentPage * itemsPerPage, pagination.totalItems), total: pagination.totalItems }) : t('Uptime.Messages.NoItems')}
{pagination.currentPage}
)}
); }