performance improvments

This commit is contained in:
dimitar committed 2026-03-18 02:04:09 +01:00
1 parent 912981e3f3
commit 02c9681aca
13 files changed
+805 -474

No files matched your search

+33 -107
View File
@@ -1,86 +1,40 @@
"use client";
import { useEffect, useState } from "react";
import { useState } from "react";
import { useUser } from "@clerk/nextjs";
import log from "@/lib/logger";
import { toast } from "@/lib/toast";
interface User {
id: string;
firstName: string;
lastName: string;
email: string;
}
interface Recommendation {
id: string;
userId: string;
content: string;
recommendationText: string;
activityPlan: string;
dietPlan: string;
status: string;
createdAt: Date;
}
import {
useUsers,
useRecommendations,
useGenerateRecommendations,
useApproveRecommendation,
useUpdateRecommendation,
type Recommendation,
} from "@/hooks/use-api";
export default function RecommendationsPage() {
const { user } = useUser();
const [users, setUsers] = useState<User[]>([]);
const [pendingRecommendations, setPendingRecommendations] = useState<
Recommendation[]
>([]);
const [loading, setLoading] = useState(true);
const [generating, setGenerating] = useState<string | null>(null);
const [useExternalModel, setUseExternalModel] = useState(false);
useEffect(() => {
fetchData();
}, []);
const { data: users = [], isLoading: usersLoading } = useUsers();
const { data: allRecommendations = [], isLoading: recsLoading } =
useRecommendations();
const pendingRecommendations = allRecommendations.filter(
(r) => r.status === "pending",
);
const fetchData = async () => {
try {
// Fetch users - API returns { success: true, data: { users: [...] }, meta: {...} }
const usersRes = await fetch("/api/users");
const usersResult = await usersRes.json();
const usersArray = usersResult.data?.users || usersResult.users || [];
setUsers(usersArray);
// Fetch pending recommendations - API returns { success: true, data: { recommendations: [...] }, meta: {...} }
const recsRes = await fetch("/api/recommendations");
const recsResult = await recsRes.json();
const allRecs =
recsResult.data?.recommendations || recsResult.recommendations || [];
setPendingRecommendations(
allRecs.filter((r: Recommendation) => r.status === "pending"),
);
} catch (error) {
log.error("Failed to fetch data", error);
} finally {
setLoading(false);
}
};
const generateRec = useGenerateRecommendations();
const approveRec = useApproveRecommendation();
const updateRec = useUpdateRecommendation();
const handleGenerate = async (userId: string) => {
setGenerating(userId);
try {
const res = await fetch("/api/recommendations/generate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ userId, useExternalModel }),
});
if (!res.ok) {
const error = await res.json();
toast.error(`Error: ${error.error}`);
} else {
toast.success("Recommendation generated successfully!");
fetchData(); // Refresh data
}
await generateRec.mutateAsync(userId);
toast.success("Recommendation generated successfully!");
} catch (error) {
log.error("Failed to generate recommendation", error);
toast.error("Failed to generate recommendation.");
} finally {
setGenerating(null);
}
};
@@ -89,25 +43,11 @@ export default function RecommendationsPage() {
status: "approved" | "rejected",
) => {
try {
const res = await fetch("/api/recommendations/approve", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
recommendationId,
status,
approvedBy: user?.id || "admin",
}),
await approveRec.mutateAsync({
recommendationId,
approved: status === "approved",
});
if (!res.ok) {
const errorData = await res.json();
toast.error(
`Failed to update status: ${errorData.error || "Unknown error"}`,
);
} else {
toast.success("Recommendation status updated");
fetchData(); // Refresh data
}
toast.success("Recommendation status updated");
} catch (error) {
log.error("Failed to approve recommendation", error);
toast.error("Error processing request");
@@ -124,38 +64,24 @@ export default function RecommendationsPage() {
newActivityPlan === null ||
newDietPlan === null
) {
// User cancelled one of the prompts
return;
}
try {
const res = await fetch("/api/recommendations", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: rec.id,
content: newContent,
activityPlan: newActivityPlan,
dietPlan: newDietPlan,
}),
await updateRec.mutateAsync({
id: rec.id,
content: newContent,
activityPlan: newActivityPlan,
dietPlan: newDietPlan,
});
if (!res.ok) {
const errorData = await res.json();
toast.error(
`Failed to update recommendation: ${errorData.error || "Unknown error"}`,
);
} else {
toast.success("Recommendation updated successfully!");
fetchData(); // Refresh data
}
toast.success("Recommendation updated successfully!");
} catch (error) {
log.error("Failed to update recommendation", error);
toast.error("Failed to update recommendation.");
}
};
if (loading) {
if (usersLoading || recsLoading) {
return (
<div className="flex items-center justify-center h-screen">
<div className="text-xl">Loading...</div>
@@ -215,10 +141,10 @@ export default function RecommendationsPage() {
</div>
<button
onClick={() => handleGenerate(user.id)}
disabled={generating === user.id}
disabled={generateRec.isPending}
className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 disabled:opacity-50"
>
{generating === user.id ? "Generating..." : "Generate"}
{generateRec.isPending ? "Generating..." : "Generate"}
</button>
</li>
))}