mirror of
https://github.com/kjanat/livedash-node.git
synced 2026-02-13 21:35:44 +01:00
fix: resolve Prettier markdown code block parsing errors
- Fix syntax errors in skills markdown files (.github/skills, .opencode/skills) - Change typescript to tsx for code blocks with JSX - Replace ellipsis (...) in array examples with valid syntax - Separate CSS from TypeScript into distinct code blocks - Convert JavaScript object examples to valid JSON in docs - Fix enum definitions with proper comma separation
This commit is contained in:
@@ -16,8 +16,13 @@ import {
|
||||
} from "lucide-react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { signOut, useSession } from "next-auth/react";
|
||||
import { useCallback, useEffect, useId, useMemo, useState } from "react";
|
||||
import ModernBarChart from "@/components/charts/bar-chart";
|
||||
import ModernDonutChart from "@/components/charts/donut-chart";
|
||||
import ModernLineChart from "@/components/charts/line-chart";
|
||||
import GeographicMap from "@/components/GeographicMap";
|
||||
import ResponseTimeDistribution from "@/components/ResponseTimeDistribution";
|
||||
import TopQuestionsChart from "@/components/TopQuestionsChart";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
@@ -27,19 +32,14 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import MetricCard from "@/components/ui/metric-card";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { authClient } from "@/lib/auth/client";
|
||||
import { formatEnumValue } from "@/lib/format-enums";
|
||||
import ModernBarChart from "../../../components/charts/bar-chart";
|
||||
import ModernDonutChart from "../../../components/charts/donut-chart";
|
||||
import ModernLineChart from "../../../components/charts/line-chart";
|
||||
import GeographicMap from "../../../components/GeographicMap";
|
||||
import ResponseTimeDistribution from "../../../components/ResponseTimeDistribution";
|
||||
import TopQuestionsChart from "../../../components/TopQuestionsChart";
|
||||
import MetricCard from "../../../components/ui/metric-card";
|
||||
import type { Company, MetricsResult } from "../../../lib/types";
|
||||
import type { Company, MetricsResult } from "@/lib/types";
|
||||
|
||||
// Dynamic import for heavy D3-based WordCloud component (~50KB)
|
||||
const WordCloud = dynamic(() => import("../../../components/WordCloud"), {
|
||||
const WordCloud = dynamic(() => import("@/components/WordCloud"), {
|
||||
ssr: false,
|
||||
loading: () => (
|
||||
<div className="h-[300px] flex items-center justify-center">
|
||||
@@ -50,7 +50,7 @@ const WordCloud = dynamic(() => import("../../../components/WordCloud"), {
|
||||
|
||||
// Safely wrapped component with useSession
|
||||
function DashboardContent() {
|
||||
const { data: session, status } = useSession();
|
||||
const { data, isPending } = authClient.useSession();
|
||||
const router = useRouter();
|
||||
const [metrics, setMetrics] = useState<MetricsResult | null>(null);
|
||||
const [company, setCompany] = useState<Company | null>(null);
|
||||
@@ -59,7 +59,7 @@ function DashboardContent() {
|
||||
const [isInitialLoad, setIsInitialLoad] = useState<boolean>(true);
|
||||
|
||||
const refreshStatusId = useId();
|
||||
const isAuditor = session?.user?.role === "AUDITOR";
|
||||
// Role-based restrictions removed - all authenticated users have same access
|
||||
|
||||
// Function to fetch metrics with optional date range
|
||||
const fetchMetrics = useCallback(
|
||||
@@ -92,19 +92,18 @@ function DashboardContent() {
|
||||
|
||||
useEffect(() => {
|
||||
// Redirect if not authenticated
|
||||
if (status === "unauthenticated") {
|
||||
router.push("/login");
|
||||
if (!isPending && !data?.session) {
|
||||
router.push("/auth/sign-in");
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch metrics and company on mount if authenticated
|
||||
if (status === "authenticated" && isInitialLoad) {
|
||||
if (!isPending && data?.session && isInitialLoad) {
|
||||
fetchMetrics(undefined, undefined, true);
|
||||
}
|
||||
}, [status, router, isInitialLoad, fetchMetrics]);
|
||||
}, [isPending, data, router, isInitialLoad, fetchMetrics]);
|
||||
|
||||
const handleRefresh = useCallback(async () => {
|
||||
if (isAuditor) return;
|
||||
if (!company?.id) {
|
||||
alert("Cannot refresh: Company ID is missing");
|
||||
return;
|
||||
@@ -132,7 +131,7 @@ function DashboardContent() {
|
||||
} finally {
|
||||
setRefreshing(false);
|
||||
}
|
||||
}, [isAuditor, company?.id]);
|
||||
}, [company?.id]);
|
||||
|
||||
// Memoized data preparation - must be before any early returns (Rules of Hooks)
|
||||
const sentimentData = useMemo(() => {
|
||||
@@ -222,7 +221,7 @@ function DashboardContent() {
|
||||
}, [metrics?.avgResponseTime]);
|
||||
|
||||
// Show loading state while session status is being determined
|
||||
if (status === "loading") {
|
||||
if (isPending) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-[60vh]">
|
||||
<div className="text-center space-y-4">
|
||||
@@ -233,7 +232,7 @@ function DashboardContent() {
|
||||
);
|
||||
}
|
||||
|
||||
if (status === "unauthenticated") {
|
||||
if (!isPending && !data?.session) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-[60vh]">
|
||||
<div className="text-center">
|
||||
@@ -335,7 +334,7 @@ function DashboardContent() {
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
onClick={handleRefresh}
|
||||
disabled={refreshing || isAuditor}
|
||||
disabled={refreshing}
|
||||
size="sm"
|
||||
className="gap-2"
|
||||
aria-label={
|
||||
@@ -369,7 +368,15 @@ function DashboardContent() {
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem
|
||||
onClick={() => signOut({ callbackUrl: "/login" })}
|
||||
onClick={async () => {
|
||||
await authClient.signOut({
|
||||
fetchOptions: {
|
||||
onSuccess: () => {
|
||||
window.location.href = "/auth/sign-in";
|
||||
},
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<LogOut className="h-4 w-4 mr-2" aria-hidden="true" />
|
||||
Sign out
|
||||
|
||||
Reference in New Issue
Block a user