{sortedMemoList.map((memo) => props.renderer(memo))}
{state.isRequesting && (
@@ -84,10 +78,10 @@ const PagedMemoList = (props: Props) => {
{t("memo.load-more")}
- {shouldShowBackToTop &&
}
+
>
)}
- {shouldShowBackToTop &&
}
+
)}
>
diff --git a/web/src/components/RenameTagDialog.tsx b/web/src/components/RenameTagDialog.tsx
index 3e14d95b..dbb1a89d 100644
--- a/web/src/components/RenameTagDialog.tsx
+++ b/web/src/components/RenameTagDialog.tsx
@@ -6,7 +6,7 @@ import { toast } from "react-hot-toast";
import { memoServiceClient } from "@/grpcweb";
import useCurrentUser from "@/hooks/useCurrentUser";
import useLoading from "@/hooks/useLoading";
-import { useMemoMetadataStore } from "@/store/v1";
+import { useUserStatsStore } from "@/store/v1";
import { useTranslate } from "@/utils/i18n";
import { generateDialog } from "./Dialog";
@@ -17,7 +17,7 @@ interface Props extends DialogProps {
const RenameTagDialog: React.FC
= (props: Props) => {
const { tag, destroy } = props;
const t = useTranslate();
- const memoMetadataStore = useMemoMetadataStore();
+ const userStatsStore = useUserStatsStore();
const [newName, setNewName] = useState(tag);
const requestState = useLoading(false);
const user = useCurrentUser();
@@ -43,7 +43,7 @@ const RenameTagDialog: React.FC = (props: Props) => {
newTag: newName,
});
toast.success("Rename tag successfully");
- memoMetadataStore.fetchMemoMetadata({ user });
+ userStatsStore.listUserStats(user.name);
} catch (error: any) {
console.error(error);
toast.error(error.details);
diff --git a/web/src/components/UserStatisticsView.tsx b/web/src/components/StatisticsView.tsx
similarity index 74%
rename from web/src/components/UserStatisticsView.tsx
rename to web/src/components/StatisticsView.tsx
index 4a8cb872..bbd69191 100644
--- a/web/src/components/UserStatisticsView.tsx
+++ b/web/src/components/StatisticsView.tsx
@@ -7,25 +7,18 @@ import { useState } from "react";
import useAsyncEffect from "@/hooks/useAsyncEffect";
import useCurrentUser from "@/hooks/useCurrentUser";
import i18n from "@/i18n";
-import { useMemoFilterStore, useMemoMetadataStore } from "@/store/v1";
+import { useMemoFilterStore, useUserStatsStore } from "@/store/v1";
+import { UserStats_MemoTypeStats } from "@/types/proto/api/v1/user_service";
import { useTranslate } from "@/utils/i18n";
import ActivityCalendar from "./ActivityCalendar";
-interface UserMemoStats {
- link: number;
- taskList: number;
- code: number;
- incompleteTasks: number;
-}
-
-const UserStatisticsView = () => {
+const StatisticsView = () => {
const t = useTranslate();
const currentUser = useCurrentUser();
const memoFilterStore = useMemoFilterStore();
- const memoMetadataStore = useMemoMetadataStore();
- const metadataList = Object.values(memoMetadataStore.getState().dataMapByName);
+ const userStatsStore = useUserStatsStore();
const [memoAmount, setMemoAmount] = useState(0);
- const [memoStats, setMemoStats] = useState({ link: 0, taskList: 0, code: 0, incompleteTasks: 0 });
+ const [memoTypeStats, setMemoTypeStats] = useState(UserStats_MemoTypeStats.fromPartial({}));
const [activityStats, setActivityStats] = useState>({});
const [selectedDate] = useState(new Date());
const [visibleMonthString, setVisibleMonthString] = useState(dayjs(selectedDate.toDateString()).format("YYYY-MM"));
@@ -35,26 +28,21 @@ const UserStatisticsView = () => {
const singularOrPluralDay = (days > 0 ? t("common.days") : t("common.day")).toLowerCase();
useAsyncEffect(async () => {
- const memoStats: UserMemoStats = { link: 0, taskList: 0, code: 0, incompleteTasks: 0 };
- metadataList.forEach((memo) => {
- const { property } = memo;
- if (property?.hasLink) {
- memoStats.link += 1;
+ const memoTypeStats = UserStats_MemoTypeStats.fromPartial({});
+ const displayTimeList: Date[] = [];
+ for (const stats of Object.values(userStatsStore.userStatsByName)) {
+ displayTimeList.push(...stats.memoDisplayTimestamps);
+ if (stats.memoTypeStats) {
+ memoTypeStats.codeCount += stats.memoTypeStats.codeCount;
+ memoTypeStats.linkCount += stats.memoTypeStats.linkCount;
+ memoTypeStats.todoCount += stats.memoTypeStats.todoCount;
+ memoTypeStats.undoCount += stats.memoTypeStats.undoCount;
}
- if (property?.hasTaskList) {
- memoStats.taskList += 1;
- }
- if (property?.hasCode) {
- memoStats.code += 1;
- }
- if (property?.hasIncompleteTasks) {
- memoStats.incompleteTasks += 1;
- }
- });
- setMemoStats(memoStats);
- setMemoAmount(metadataList.length);
- setActivityStats(countBy(metadataList.map((memo) => dayjs(memo.displayTime).format("YYYY-MM-DD"))));
- }, [memoMetadataStore.stateId]);
+ }
+ setMemoTypeStats(memoTypeStats);
+ setMemoAmount(displayTimeList.length);
+ setActivityStats(countBy(displayTimeList.map((date) => dayjs(date).format("YYYY-MM-DD"))));
+ }, [userStatsStore.stateId]);
const onCalendarClick = (date: string) => {
memoFilterStore.removeFilter((f) => f.factor === "displayTime");
@@ -110,26 +98,26 @@ const UserStatisticsView = () => {
{t("memo.links")}