Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pipipi #3087

Merged
merged 14 commits into from
Dec 20, 2024
Merged

Pipipi #3087

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 33 additions & 12 deletions bifrost/app/pi/first_page/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,51 @@ import { useRouter } from "next/navigation";
import { Suspense } from "react";
import { useHeliconeLogin } from "./../useHeliconeLogin";
import { useTestAPIKey } from "./useTestApiKey";
import { useQuery } from "@tanstack/react-query";

const jetbrainsMono = JetBrains_Mono({ subsets: ["latin"] });

const FirstPageContent = () => {
const jawn = useJawnClient();
const { apiKey, sessionUUID } = useHeliconeLogin();
const { data, isLoading } = useTestAPIKey(apiKey.data ?? "");
const jawn = useJawnClient(apiKey.data ?? "");
Comment on lines 15 to +16
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: passing empty string as fallback for apiKey.data could trigger unnecessary API calls - consider adding enabled: !!apiKey.data to useTestAPIKey

const router = useRouter();

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: all three useQuery hooks should include enabled: !!apiKey.data to prevent unnecessary API calls when apiKey is not available

if ((!data && !isLoading) || !apiKey.data) {
router.push("/pi/total-requests");
const orgName = useQuery({
queryKey: ["org-name", apiKey.data],
queryFn: () => jawn.POST("/v1/pi/org-name/query"),
});

const totalCosts = useQuery({
queryKey: ["total-costs", apiKey.data],
queryFn: () => jawn.POST("/v1/pi/total-costs"),
});

const costsOverTime = useQuery({
queryKey: ["costs-over-time", apiKey.data],
queryFn: () =>
jawn.POST("/v1/pi/costs-over-time/query", {
body: {
userFilter: "all",
dbIncrement: "day",
timeZoneDifference: new Date().getTimezoneOffset(),
timeFilter: {
start: new Date(
Date.now() - 30 * 24 * 60 * 60 * 1000
).toISOString(),
end: new Date().toISOString(),
},
},
}),
});

if (!data && !isLoading && !apiKey.data && !apiKey.isLoading) {
router.push("/pi/setup?invalid_api_key=true");
Comment on lines +46 to 49
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: showing Loading... while redirecting may cause UI flicker - consider removing the loading message since the redirect happens immediately

return <div>Loading...</div>;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: returning an empty div after fetching data is likely unintentional - component should render fetched data or loading states


return (
<div className="w-full flex flex-col justify-center items-center h-[100vh]">
<h1
className={`text-3xl font-extrabold truncate max-w-[80vw] ${jetbrainsMono.className} py-2`}
>
LOGGED IN! WOOOHOO
</h1>
{data && JSON.stringify(data).slice(0, 100)}
</div>
);
return <div></div>;
};

const PiPage = () => {
Expand Down
12 changes: 6 additions & 6 deletions bifrost/app/pi/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ const jetbrainsMono = JetBrains_Mono({ subsets: ["latin"] });

const PiPageContent = () => {
return (
<div className="w-full flex flex-col justify-center items-center h-[100vh]">
<h1
className={`text-3xl font-extrabold truncate max-w-[80vw] ${jetbrainsMono.className} py-2`}
>
<div
className={`w-full flex flex-col justify-center items-center h-[100vh] ${jetbrainsMono.className}`}
>
<h1 className={`text-3xl font-extrabold truncate max-w-[80vw] py-2`}>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: extra space before py-2 in className string

Welcome to Helicone!
</h1>

<div className="relative h-[80vh]">
<Image
src="/static/pi/intro-image.png"
src="/static/pi/intro-image.webp"
alt="Helicone Logo"
width={460}
height={360}
Expand All @@ -31,7 +31,7 @@ const PiPageContent = () => {

<Link
href="/pi/setup"
className=" bg-blue-500 p-5 bg-opacity-60 absolute top-1/2 left-1/2 transform translate-x-[30px] -translate-y-[110px] text-white font-bold"
className="p-5 border-2 absolute top-1/2 left-1/2 transform translate-x-[16px] -translate-y-[90px] text-black font-bold h-[36.17px] px-[12.17px] py-[6.08px] origin-top-left -rotate-1 bg-white border-l-2 border-r-4 border-t-2 border-b-4 border-black flex-col justify-start items-start gap-[10.14px] inline-flex"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: extra space after border-2 in className string

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: height and padding values conflict - h-[36.17px] with p-5 will make element taller than specified height

>
Start
</Link>
Expand Down
6 changes: 3 additions & 3 deletions bifrost/app/pi/setup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ const PiPageContent = () => {
);
const { data, isLoading } = useTestAPIKey(apiKey.data ?? "");

if (apiKey.data && data && !isLoading) {
router.push("/pi/first_page");
if (apiKey.data && data && !isLoading && !apiKey.isLoading) {
router.push("/pi/total-requests");
return <div>Loading...</div>;
}

Expand All @@ -34,7 +34,7 @@ const PiPageContent = () => {

<div className="relative h-[80vh]">
<Image
src="/static/pi/intro-image.png"
src="/static/pi/intro-image.webp"
alt="Helicone Logo"
width={460}
height={360}
Expand Down
135 changes: 135 additions & 0 deletions bifrost/app/pi/total-cost/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
"use client";

import { useRouter } from "next/navigation";
import { useHeliconeLogin } from "../useHeliconeLogin";
import Link from "next/link";

import { JetBrains_Mono } from "next/font/google";
import { useTestAPIKey } from "../first_page/useTestApiKey";
import { useJawnClient } from "@/lib/clients/jawnHook";
import { useQuery } from "@tanstack/react-query";
import {
Bar,
BarChart,
CartesianGrid,
ResponsiveContainer,
XAxis,
YAxis,
} from "recharts";
const jetbrainsMono = JetBrains_Mono({ subsets: ["latin"] });

const TotalCost = () => {
const { apiKey } = useHeliconeLogin();
const { data, isLoading } = useTestAPIKey(apiKey.data ?? "");
const router = useRouter();

const jawn = useJawnClient(apiKey.data ?? "");

const totalRequests = useQuery({
queryKey: ["total-requests", apiKey.data],
queryFn: () => jawn.POST("/v1/pi/total_requests"),
});
Comment on lines +28 to +31
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: totalRequests is fetched but never used in the component


const costsOverTime = useQuery({
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: no error handling or loading state for costsOverTime query

queryKey: ["costs-over-time", apiKey.data],
queryFn: () =>
jawn.POST("/v1/pi/costs-over-time/query", {
body: {
userFilter: "all",
dbIncrement: "day",
timeZoneDifference: new Date().getTimezoneOffset(),
timeFilter: {
start: new Date(
Date.now() - 30 * 24 * 60 * 60 * 1000
).toISOString(),
end: new Date().toISOString(),
},
},
}),
});
const costsOverTimeData = costsOverTime.data?.data?.data;

if (!data && !isLoading && !apiKey.data && !apiKey.isLoading) {
router.push("/pi/setup?invalid_api_key=true");
return null;
}

return (
<div
className={`w-full flex flex-col justify-center items-center h-[100vh] p-5 gap-4 ${jetbrainsMono.className}`}
>
<div className="w-full h-[360px] bg-white relative border-2 border-black">
<div className="p-2.5 bg-white border-2 border-black border-r-4 border-b-4 flex flex-col gap-[3px] absolute top-[22px] left-[18px]">
<div className="text-[14px] font-medium">Total Cost</div>
<div className="text-[21px] font-extrabold">
$
{costsOverTimeData
?.reduce((sum, item) => sum + item.cost, 0)
?.toFixed(2) ?? "0.00"}
</div>
</div>
<div className="px-3 py-1 bg-white border-2 border-black border-r-4 border-b-4 absolute top-[22px] right-[18px] flex gap-3 z-10 items-center">
<div className="bg-[#E5E5E5] w-[9.14px] h-[9.14px] border-2 border-black border-r-4 border-b-4"></div>
<div className="text-[14px] font-medium leading-tight">costs</div>
</div>
<ResponsiveContainer width="100%" height="100%" className=" m-0 p-0">
<BarChart data={costsOverTimeData ?? []} className="m-0 p-0">
<CartesianGrid
vertical={false}
color="#000000"
opacity={0.3}
strokeWidth={1.52}
/>
<XAxis
dataKey="created_at_trunc"
tickFormatter={(value) =>
new Date(value).toLocaleDateString(undefined, {
month: "numeric",
day: "numeric",
year: "2-digit",
})
}
includeHidden
interval={6}
tickSize={14}
padding={{ left: 16, right: 16 }}
tickMargin={8}
fontSize={12}
strokeWidth={1.52}
stroke="#000000"
/>
{/* <YAxis fontSize={12} /> */}
<Bar
dataKey="cost"
fill="#888888"
radius={[0, 0, 0, 0]}
stroke="#000000" // Add black outline
strokeWidth={1.52} // Set outline thickness
/>
</BarChart>
</ResponsiveContainer>
</div>
<div className="flex justify-between items-center w-full">
<Link href="/pi/total-requests">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="/static/pi/arrow-left.webp"
alt="arrow-left"
className="w-16 h-16"
/>
</Link>

<Link href="/pi/total-requests">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src="/static/pi/arrow-right.webp"
alt="arrow-right"
className="w-16 h-16"
/>
</Link>
</div>
</div>
);
};

export default TotalCost;
Loading
Loading