Skip to content

Commit

Permalink
add data analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
walteh committed Jul 16, 2024
1 parent 7ee5b54 commit 600d13a
Show file tree
Hide file tree
Showing 23 changed files with 1,143 additions and 273 deletions.
2 changes: 1 addition & 1 deletion .bun-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.18
1.1.20
Binary file modified bun.lockb
Binary file not shown.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@typescript-eslint/parser": "^7.13.1",
"@vitejs/plugin-basic-ssl": "^1.1.0",
"@vitejs/plugin-react-swc": "^3.5.0",
"animate.css": "^4.1.1",
"apexcharts": "^3.49.2",
"autoprefixer": "^10.4.19",
"body-parser": "^1.20.2",
Expand All @@ -67,6 +68,7 @@
"react-apexcharts": "^1.4.1",
"react-icons": "^5.2.1",
"react-router-dom": "^6.23.1",
"simple-statistics": "^7.8.3",
"tailwindcss": "^3.4.4",
"ts-node": "^10.9.2",
"typescript": "^5.2.2",
Expand Down
4 changes: 2 additions & 2 deletions src/client/cache_store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
AccessTokenResponse,
BreakdownMetricTypeMap,
ConversationResponse,
MediaMetricTypeMap,
SimplifedMediaMetricTypeMap,
SimplifedMetricTypeMap,
ThreadMedia,
UserProfileResponse,
Expand All @@ -24,7 +24,7 @@ export interface UserDataTypes {

export interface NestedUserDataTypes {
user_threads_replies: ConversationResponse;
user_threads_insights: MediaMetricTypeMap;
user_threads_insights: SimplifedMediaMetricTypeMap;
}

interface DataResponse<T extends keyof UserDataTypes> {
Expand Down
39 changes: 39 additions & 0 deletions src/client/hooks/useInsightsByDate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { isbd, isdbAll, isdbRange } from "@src/lib/ml";
import { SimplifedMediaMetricTypeMap, SimplifedMetricTypeMap } from "@src/threadsapi/types";

import useCacheStore from "./useCacheStore";

const useInsightsByDate = (date: Date) => {
const userInsights = useCacheStore((state) => state.user_insights?.data ?? ({} as SimplifedMetricTypeMap));
const userThreads = Object.values(useCacheStore((state) => state.user_threads?.data ?? {}));
const userThreadsInsights = useCacheStore((state) => state.user_threads_insights?.data ?? {}) as Record<
string,
{ data: SimplifedMediaMetricTypeMap }
>;

return isbd(date.toISOString().slice(0, 10), userInsights, userThreads, userThreadsInsights);
};

export const useInsightsByDateRange = (startDate: Date, endDate: Date) => {
const userInsights = useCacheStore((state) => state.user_insights?.data ?? ({} as SimplifedMetricTypeMap));
const userThreads = Object.values(useCacheStore((state) => state.user_threads?.data ?? {}));
const userThreadsInsights = useCacheStore((state) => state.user_threads_insights?.data ?? {}) as Record<
string,
{ data: SimplifedMediaMetricTypeMap }
>;

return isdbRange(startDate, endDate, userInsights, userThreads, userThreadsInsights);
};

export const useInsightsByAll = () => {
const userInsights = useCacheStore((state) => state.user_insights?.data ?? ({} as SimplifedMetricTypeMap));
const userThreads = Object.values(useCacheStore((state) => state.user_threads?.data ?? {}));
const userThreadsInsights = useCacheStore((state) => state.user_threads_insights?.data ?? {}) as Record<
string,
{ data: SimplifedMediaMetricTypeMap }
>;

return isdbAll(userInsights, userThreads, userThreadsInsights);
};

export default useInsightsByDate;
8 changes: 4 additions & 4 deletions src/client/hooks/useThreadInfoCallbacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const useThreadInfoCallbacks = () => {
(thread: ThreadMedia) => {
const dat = userThreadsInsights?.data;
if (!dat) return 0;
return dat[thread.id]?.data.likes?.values[0].value ?? 0;
return dat[thread.id]?.data.total_likes ?? 0;
},
[userThreadsInsights],
);
Expand All @@ -21,7 +21,7 @@ const useThreadInfoCallbacks = () => {
(thread: ThreadMedia) => {
const dat = userThreadsInsights?.data;
if (!dat) return 0;
return dat[thread.id]?.data.views?.values[0].value ?? 0;
return dat[thread.id]?.data.total_views ?? 0;
},
[userThreadsInsights],
);
Expand All @@ -30,7 +30,7 @@ const useThreadInfoCallbacks = () => {
(thread: ThreadMedia) => {
const dat = userThreadsInsights?.data;
if (!dat) return 0;
return dat[thread.id]?.data.quotes?.values[0].value ?? 0;
return dat[thread.id]?.data.total_quotes ?? 0;
},
[userThreadsInsights],
);
Expand All @@ -39,7 +39,7 @@ const useThreadInfoCallbacks = () => {
(thread: ThreadMedia) => {
const dat = userThreadsInsights?.data;
if (!dat) return 0;
return dat[thread.id]?.data.reposts?.values[0].value ?? 0;
return dat[thread.id]?.data.total_reposts ?? 0;
},
[userThreadsInsights],
);
Expand Down
11 changes: 11 additions & 0 deletions src/client/hooks/useTimePeriod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ const getCurrentTimePeriods = (): Record<TimePeriodLabel, TimePeriod> => {
const label = date.toLocaleDateString("default", { year: "numeric", month: "long" }) as TimePeriodLabel;
const start_date = new Date(date.getFullYear(), date.getMonth(), 1);
const end_date = new Date(date.getFullYear(), date.getMonth() + 1, 0);
if (end_date > new Date()) {
return { label, start_date, end_date: new Date() };
}
return { label, start_date, end_date };
});

Expand All @@ -61,6 +64,11 @@ const getCurrentTimePeriods = (): Record<TimePeriodLabel, TimePeriod> => {
start_date: new Date(today.getFullYear(), today.getMonth(), today.getDate() - 7),
end_date: today,
};
const last14days = {
label: "last14days" as TimePeriodLabel,
start_date: new Date(today.getFullYear(), today.getMonth(), today.getDate() - 14),
end_date: today,
};
const last30days = {
label: "last30days" as TimePeriodLabel,
start_date: new Date(today.getFullYear(), today.getMonth(), today.getDate() - 30),
Expand All @@ -74,6 +82,7 @@ const getCurrentTimePeriods = (): Record<TimePeriodLabel, TimePeriod> => {

return {
last7days, // "last7days" as TimePeriodLabel,
last14days,
last30days,
last90days,
...Object.fromEntries(monthPeriods.map((period) => [period.label, period])),
Expand All @@ -84,6 +93,8 @@ export const useTimePeriodListOfDays = (period: TimePeriod): string[] => {
return useMemo(() => {
const days = [];
for (let d = new Date(period.start_date); d <= period.end_date; d.setDate(d.getDate() + 1)) {
// make sure its not greater than today

days.push(new Date(d).toISOString().slice(0, 10));
}
return days;
Expand Down
189 changes: 189 additions & 0 deletions src/components/DailyReportView copy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { useMemo, useState } from "react";

import useInsightsByDate from "@src/client/hooks/useInsightsByDate";

function percentChange(a: number, b: number): number {
const change = Math.round(((a - b) / b) * 10000) / 100;
return change;
}

const ONE_DAY = 1000 * 60 * 60 * 24;

const Day: React.FC<{ date: Date }> = ({ date }) => {
const today = useInsightsByDate(date);

const yesterday = useInsightsByDate(new Date(date.getTime() - ONE_DAY * 1));

const lastWeek = useInsightsByDate(new Date(date.getTime() - ONE_DAY * 6));

const secondLastWeek = useInsightsByDate(new Date(date.getTime() - ONE_DAY * 13));

const thirdLastWeek = useInsightsByDate(new Date(date.getTime() - ONE_DAY * 20));
// const viewsLastWeek = useCacheStore((state) => state.user_insights?.data?.views?.values[6]);

const mem = useMemo(() => {
const stats = [
{
name: "total views",
value: today.totalUserViews,
changeFromYesterday: percentChange(today.totalUserViews, yesterday.totalUserViews),
changeFromLastWeek: percentChange(today.totalUserViews, lastWeek.totalUserViews),
changeFromSecondLastWeek: percentChange(today.totalUserViews, secondLastWeek.totalUserViews),
changeFromThirdLastWeek: percentChange(today.totalUserViews, thirdLastWeek.totalUserViews),
},
{
name: "likes",
value: today.cumlativePostInsights.total_likes,
changeFromYesterday: percentChange(today.cumlativePostInsights.total_likes, yesterday.cumlativePostInsights.total_likes),
changeFromLastWeek: percentChange(today.cumlativePostInsights.total_likes, lastWeek.cumlativePostInsights.total_likes),
changeFromSecondLastWeek: percentChange(
today.cumlativePostInsights.total_likes,
secondLastWeek.cumlativePostInsights.total_likes,
),
changeFromThirdLastWeek: percentChange(
today.cumlativePostInsights.total_likes,
thirdLastWeek.cumlativePostInsights.total_likes,
),
},
{
name: "views",
value: today.cumlativePostInsights.total_views,
changeFromYesterday: percentChange(today.cumlativePostInsights.total_views, yesterday.cumlativePostInsights.total_views),
changeFromLastWeek: percentChange(today.cumlativePostInsights.total_views, lastWeek.cumlativePostInsights.total_views),
changeFromSecondLastWeek: percentChange(
today.cumlativePostInsights.total_views,
secondLastWeek.cumlativePostInsights.total_views,
),
changeFromThirdLastWeek: percentChange(
today.cumlativePostInsights.total_views,
thirdLastWeek.cumlativePostInsights.total_views,
),
},
{
name: "replies",
value: today.cumlativePostInsights.total_replies,
changeFromYesterday: percentChange(
today.cumlativePostInsights.total_replies,
yesterday.cumlativePostInsights.total_replies,
),
changeFromLastWeek: percentChange(today.cumlativePostInsights.total_replies, lastWeek.cumlativePostInsights.total_replies),
changeFromSecondLastWeek: percentChange(
today.cumlativePostInsights.total_replies,
secondLastWeek.cumlativePostInsights.total_replies,
),
changeFromThirdLastWeek: percentChange(
today.cumlativePostInsights.total_replies,
thirdLastWeek.cumlativePostInsights.total_replies,
),
},
{
name: "reposts",
value: today.cumlativePostInsights.total_reposts,
changeFromYesterday: percentChange(
today.cumlativePostInsights.total_reposts,
yesterday.cumlativePostInsights.total_reposts,
),
changeFromLastWeek: percentChange(today.cumlativePostInsights.total_reposts, lastWeek.cumlativePostInsights.total_reposts),
changeFromSecondLastWeek: percentChange(
today.cumlativePostInsights.total_reposts,
secondLastWeek.cumlativePostInsights.total_reposts,
),
changeFromThirdLastWeek: percentChange(
today.cumlativePostInsights.total_reposts,
thirdLastWeek.cumlativePostInsights.total_reposts,
),
},
{
name: "quotes",
value: today.cumlativePostInsights.total_quotes,
changeFromYesterday: percentChange(today.cumlativePostInsights.total_quotes, yesterday.cumlativePostInsights.total_quotes),
changeFromLastWeek: percentChange(today.cumlativePostInsights.total_quotes, lastWeek.cumlativePostInsights.total_quotes),
changeFromSecondLastWeek: percentChange(
today.cumlativePostInsights.total_quotes,
secondLastWeek.cumlativePostInsights.total_quotes,
),
changeFromThirdLastWeek: percentChange(
today.cumlativePostInsights.total_quotes,
thirdLastWeek.cumlativePostInsights.total_quotes,
),
},
];

return stats;
}, [today, yesterday, lastWeek, secondLastWeek, thirdLastWeek]);

return (
<div className="p-6 bg-gray-100 rounded-lg shadow-md space-y-6">
<h1 className="text-3xl font-bold text-gray-900">Daily Report for {date.toDateString()}</h1>
{mem.map((stat) => (
<div key={stat.name} className="p-4 bg-white rounded-lg shadow-md">
<h2 className="text-xl font-bold text-gray-700">{stat.name}</h2>
<p className="text-2xl font-semibold text-gray-900">{stat.value}</p>
<div className="mt-2">
<p className="text-sm text-gray-600">
Change from yesterday:{" "}
<span className={stat.changeFromYesterday > 0 ? "text-green-500" : "text-red-500"}>
{stat.changeFromYesterday}%
</span>
</p>
<p className="text-sm text-gray-600">
Change from last week:{" "}
<span className={stat.changeFromLastWeek > 0 ? "text-green-500" : "text-red-500"}>
{stat.changeFromLastWeek}%
</span>
</p>
<p className="text-sm text-gray-600">
Change from second last week:{" "}
<span className={stat.changeFromSecondLastWeek > 0 ? "text-green-500" : "text-red-500"}>
{stat.changeFromSecondLastWeek}%
</span>
</p>
<p className="text-sm text-gray-600">
Change from third last week:{" "}
<span className={stat.changeFromThirdLastWeek > 0 ? "text-green-500" : "text-red-500"}>
{stat.changeFromThirdLastWeek}%
</span>
</p>
</div>
</div>
))}
</div>
);
};

export default function DailyReportView() {
const [date, setDate] = useState(new Date());

console.log("date", date);

return (
<div className="bg-gray-50 dark:bg-gray-900">
<div className="py-12 sm:py-16 lg:py-24">
{/* transition out to the right, and in from the left */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 animate__animated animate__slideInLeft">
<Day date={date} />
</div>

{/* arrows to move between days */}
<div className="mt-8 flex justify-center">
<button
onClick={() => {
setDate((d) => new Date(d.getTime() - ONE_DAY * 1));
}}
className="bg-white dark:bg-gray-800 dark:text-white text-gray-900 px-4 py-2 rounded-md shadow-sm"
>
Previous day
</button>
<button
onClick={() => {
setDate((d) => new Date(d.getTime() + ONE_DAY * 1));
}}
className="bg-white dark:bg-gray-800 dark:text-white text-gray-900 px-4 py-2 rounded-md shadow-sm"
>
Next day
</button>
</div>
</div>
</div>
);
}
Loading

0 comments on commit 600d13a

Please sign in to comment.