Skip to content
Open
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
16 changes: 16 additions & 0 deletions app/(app)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Logo from "../logo.gif";

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<>
<header className="pl-2 bg-[#ffdeee]">
<img src={Logo.src} />
</header>
<main>{children}</main>
</>
);
}
38 changes: 38 additions & 0 deletions app/(app)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Suspense } from "react";
import { SyntheticChart } from "../_components/synthetic-chart";
import { Iframe } from "../_components/iframe";

export default function Home() {
return (
<div className="p-4">
<h3 className="font-semibold text-xl">Preset Charts</h3>
<div className="grid md:grid-cols-2 xl:grid-cols-3">
<Iframe src={`/embed?smoothing=30&show=`} width={"100%"} height={300} />
<Iframe
src={`/embed?smoothing=30&show=&treatment_identifier=optimism&intervention_date=2023-06-01&dependent=market_cap_eth`}
width={"100%"}
height={300}
/>
<Iframe
src={`/embed?smoothing=30&show=&treatment_identifier=zksync_era&intervention_date=2024-01-01&dependent=txcount&controls_identifier=base,polygon_zkevm,loopring,metis,scroll,zksync_era,optimism`}
width={"100%"}
height={300}
/>
</div>
<h3 className="font-semibold text-xl mb-2">Embeddable iframe</h3>
<div className="bg-gray-950 text-gray-200 rounded p-2 text-sm mb-16">
<pre className="font-mono">{`<iframe
src={"https://counter-factually.vercel.app/embed?show=settings,brush,weights,smoothing&smoothing=30&treatment_identifier=optimism&intervention_date=2023-06-01&dependent=market_cap_eth"}
width={"100%"}
height={600}
/>`}</pre>
</div>
<h3 className="font-semibold text-xl mb-2">Playground</h3>
<div className="">
<Suspense>
<SyntheticChart />
</Suspense>
</div>
</div>
);
}
File renamed without changes.
23 changes: 23 additions & 0 deletions app/_components/iframe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use client";

import { ComponentProps, useEffect, useRef } from "react";

export function Iframe(props: ComponentProps<"iframe">) {
const ref = useRef<HTMLIFrameElement>(null);
useEffect(() => {
function adjustIframeHeight() {
const iframe = ref.current;
if (iframe) {
iframe.style.height =
(iframe.contentWindow?.document.body.scrollHeight ?? 0) + 50 + "px";

console.log(iframe.style.height);
}
}

addEventListener("resize", adjustIframeHeight);
adjustIframeHeight();
return () => removeEventListener("resize", adjustIframeHeight);
}, []);
return <iframe className="overflow-hidden" ref={ref} {...props} />;
}
114 changes: 52 additions & 62 deletions app/_components/synthetic-chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ import {
ChartTooltip,
ChartTooltipContent,
} from "@/components/ui/chart";
import { useApi, useChartParams } from "@/hooks/useApi";
import { Components, useApi, useChartParams } from "@/hooks/useApi";
import { Button } from "@/components/ui/button";
import { ChartSpline, TrendingUpDown } from "lucide-react";
import { format } from "date-fns";
import { cn, formatNumber, suffixNumber } from "@/lib/utils";
import { cn, suffixNumber } from "@/lib/utils";
import { networks, predictors } from "@/config";
import { Weights } from "./weights";
import { Settings } from "./settings";

const chartConfig = {
desktop: {
Expand All @@ -48,7 +50,6 @@ const chartConfig = {
export function SyntheticChart() {
const { data, isPending, error } = useApi();
const [params, setParams] = useChartParams();
console.log(123, data);

const startDate = data?.data[0]?.date;
const endDate = data?.data[data?.data.length - 1]?.date;
Expand All @@ -63,71 +64,61 @@ export function SyntheticChart() {
);
return (
<div>
<div className="mb-2 text-sm">
<h3 className="font-semibold">Weighted control networks</h3>
<div className="flex gap-2 font-mono">
Synthetic Control ={" "}
{Object.entries(data?.weights ?? {}).map(
([key, val], index, array) => (
<div key={key}>
{networks.find((network) => network.value === key)?.label}{" "}
&times; {String(val)}
<span className="font-bold">
{index < array.length - 1 && " +"}
</span>
</div>
)
)}
</div>
</div>
{params.show.includes(Components.settings) && <Settings />}
{params.show.includes(Components.brush) && <Weights />}

<Card
className={cn({
["animate-pulse opacity-50"]: isPending,
})}
className={cn(
// "border-none shadow-none",
{
["animate-pulse opacity-50"]: isPending,
}
)}
>
<CardHeader>
<CardTitle className="flex justify-between items-center">
{params.view === "default" ? "Synthetic Control" : "Impact Ratio"}

<div className="flex gap-1 items-center">
<Button
size="sm"
onClick={() => setParams({ smoothing: 1 })}
variant={params.smoothing === 1 ? "secondary" : "outline"}
>
Daily
</Button>
<Button
size="sm"
onClick={() => setParams({ smoothing: 7 })}
variant={params.smoothing === 7 ? "secondary" : "outline"}
>
7 days
</Button>
<Button
size="sm"
onClick={() => setParams({ smoothing: 30 })}
variant={params.smoothing === 30 ? "secondary" : "outline"}
>
1 month
</Button>
{params.show.includes(Components.smoothing) && (
<div className="flex gap-1 items-center">
<Button
size="sm"
onClick={() => setParams({ smoothing: 1 })}
variant={params.smoothing === 1 ? "secondary" : "outline"}
>
Daily
</Button>
<Button
size="sm"
onClick={() => setParams({ smoothing: 7 })}
variant={params.smoothing === 7 ? "secondary" : "outline"}
>
7 days
</Button>
<Button
size="sm"
onClick={() => setParams({ smoothing: 30 })}
variant={params.smoothing === 30 ? "secondary" : "outline"}
>
1 month
</Button>

<Button
size="icon"
onClick={() =>
setParams({
view: params.view === "default" ? "impact" : "default",
})
}
>
{params.view === "default" ? (
<TrendingUpDown />
) : (
<ChartSpline />
)}
</Button>
</div>
<Button
size="icon"
onClick={() =>
setParams({
view: params.view === "default" ? "impact" : "default",
})
}
>
{params.view === "default" ? (
<TrendingUpDown />
) : (
<ChartSpline />
)}
</Button>
</div>
)}
</CardTitle>
<CardDescription>
{predictors.find((p) => p.value === params.dependent)?.label}
Expand Down Expand Up @@ -194,13 +185,12 @@ export function SyntheticChart() {
dot={false}
/>
)}
<Brush />
{params.show.includes(Components.brush) && <Brush />}
<Legend
align="right"
wrapperStyle={{ fontSize: 18 }}
verticalAlign="top"
formatter={(value, entry) => {
console.log(value, params);
return value === "treatment"
? networks.find(
(network) =>
Expand Down
37 changes: 37 additions & 0 deletions app/_components/weights.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use client";

import { AlertCircle } from "lucide-react";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";

import { useApi } from "@/hooks/useApi";
import { networks } from "@/config";

export function Weights() {
const { data, error } = useApi();

if (error)
return (
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertTitle>Error</AlertTitle>
<AlertDescription>{error.toString()}</AlertDescription>
</Alert>
);
return (
<div className="mb-2 text-sm">
<h3 className="font-semibold">Weighted control networks</h3>
<div className="flex gap-2 font-mono">
Synthetic Control ={" "}
{Object.entries(data?.weights ?? {}).map(([key, val], index, array) => (
<div key={key}>
{networks.find((network) => network.value === key)?.label} &times;{" "}
{String(val)}
<span className="font-bold">
{index < array.length - 1 && " +"}
</span>
</div>
))}
</div>
</div>
);
}
8 changes: 3 additions & 5 deletions app/page.tsx → app/embed/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { Suspense } from "react";
import { Settings } from "./_components/settings";
import { SyntheticChart } from "./_components/synthetic-chart";
import { Settings } from "../_components/settings";
import { SyntheticChart } from "../_components/synthetic-chart";

export default function Home() {
export default function Embed() {
return (
<div className="p-4">
<div className="flex flex-col gap-1">
<Suspense>
<Settings />

<SyntheticChart />
</Suspense>
</div>
Expand Down
30 changes: 7 additions & 23 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import type { Metadata } from "next";
import localFont from "next/font/local";
import { NuqsAdapter } from "nuqs/adapters/next/app";
import { type ReactNode } from "react";

import Logo from "./logo.gif";
import { NuqsAdapter } from "nuqs/adapters/next/app";
import { Providers } from "./(app)/providers";
import "./globals.css";
import { Providers } from "./providers";

const geistSans = localFont({
src: "./fonts/GeistVF.woff",
Expand All @@ -18,36 +15,23 @@ const geistMono = localFont({
weight: "100 900",
});

export const metadata: Metadata = {
title: "counter factually",
export const metadata = {
title: "CounterFactually",
description: "...",
};

export default function RootLayout({
children,
}: Readonly<{
}: {
children: React.ReactNode;
}>) {
}) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<NuqsAdapter>
<Providers>
<header className="pl-2 bg-[#ffdeee]">
<img src={Logo.src} />
{/* <video
loop
playsInline
className="h-16"
autoPlay
src={"./logo.mp4"}
muted
/> */}
</header>
<main>{children}</main>
</Providers>
<Providers>{children}</Providers>
</NuqsAdapter>
</body>
</html>
Expand Down
Loading