feat(desktop): display list analytics
This commit is contained in:
parent
e0b379bba9
commit
e525edc83d
|
|
@ -1,5 +1,5 @@
|
|||
import { Skeleton } from "@follow/components/ui/skeleton/index.js"
|
||||
import type { FeedOrListRespModel } from "@follow/models"
|
||||
import type { FeedAnalyticsModel, FeedOrListRespModel, ListAnalyticsModel } from "@follow/models"
|
||||
import type { FC } from "react"
|
||||
import { useMemo } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
|
@ -11,11 +11,7 @@ import { FollowSummary } from "../feed/feed-summary"
|
|||
export interface FeedSummaryProps {
|
||||
feed: FeedOrListRespModel
|
||||
|
||||
analytics?: {
|
||||
updatesPerWeek: number | null
|
||||
subscriptionCount: number | null
|
||||
latestEntryPublishedAt: string | null
|
||||
}
|
||||
analytics?: FeedAnalyticsModel | ListAnalyticsModel
|
||||
|
||||
showAnalytics?: boolean
|
||||
}
|
||||
|
|
@ -28,7 +24,7 @@ export const FeedSummary: FC<FeedSummaryProps> = ({ feed, analytics, showAnalyti
|
|||
|
||||
{showAnalytics && (
|
||||
<div className="text-callout mt-2 flex h-6 justify-between gap-4 pl-10">
|
||||
{!analytics ? (
|
||||
{!analytics && !("updatedAt" in feed && "updatedAt" in feed && feed.updatedAt) ? (
|
||||
<Skeleton className="mt-1 h-5 w-40" />
|
||||
) : (
|
||||
<div className="text-text-secondary flex items-center gap-3">
|
||||
|
|
@ -42,12 +38,14 @@ export const FeedSummary: FC<FeedSummaryProps> = ({ feed, analytics, showAnalyti
|
|||
</span>
|
||||
</div>
|
||||
)}
|
||||
{analytics?.updatesPerWeek ? (
|
||||
{analytics && "updatesPerWeek" in analytics && analytics?.updatesPerWeek ? (
|
||||
<div className="flex items-center gap-1.5">
|
||||
<i className="i-mgc-safety-certificate-cute-re" />
|
||||
<span>{t("feed.entry_week", { count: analytics.updatesPerWeek ?? 0 })}</span>
|
||||
</div>
|
||||
) : analytics?.latestEntryPublishedAt ? (
|
||||
) : analytics &&
|
||||
"latestEntryPublishedAt" in analytics &&
|
||||
analytics?.latestEntryPublishedAt ? (
|
||||
<div className="flex items-center gap-1.5">
|
||||
<i className="i-mgc-safe-alert-cute-re" />
|
||||
<span>{t("feed.updated_at")}</span>
|
||||
|
|
@ -57,6 +55,13 @@ export const FeedSummary: FC<FeedSummaryProps> = ({ feed, analytics, showAnalyti
|
|||
/>
|
||||
</div>
|
||||
) : null}
|
||||
{"updatedAt" in feed && feed.updatedAt ? (
|
||||
<div className="flex items-center gap-1.5">
|
||||
<i className="i-mgc-safety-certificate-cute-re" />
|
||||
<span>{t("feed.updated_at")}</span>
|
||||
<RelativeTime date={feed.updatedAt} displayAbsoluteTimeAfterDay={Infinity} />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { Button } from "@follow/components/ui/button/index.js"
|
||||
import { Card, CardHeader } from "@follow/components/ui/card/index.jsx"
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
|
|
@ -13,7 +12,7 @@ import { Input } from "@follow/components/ui/input/index.js"
|
|||
import { LoadingCircle } from "@follow/components/ui/loading/index.jsx"
|
||||
import { Switch } from "@follow/components/ui/switch/index.jsx"
|
||||
import { FeedViewType } from "@follow/constants"
|
||||
import type { ListModel } from "@follow/models/types"
|
||||
import type { ListAnalyticsModel, ListModel } from "@follow/models/types"
|
||||
import { tracker } from "@follow/tracker"
|
||||
import { cn } from "@follow/utils/utils"
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
|
|
@ -31,7 +30,6 @@ import { apiClient } from "~/lib/api-fetch"
|
|||
import { tipcClient } from "~/lib/client"
|
||||
import { getFetchErrorMessage, toastFetchError } from "~/lib/error-parser"
|
||||
import { getNewIssueUrl } from "~/lib/issues"
|
||||
import { FollowSummary } from "~/modules/feed/feed-summary"
|
||||
import { entries as entriesQuery } from "~/queries/entries"
|
||||
import { lists as listsQuery, useList } from "~/queries/lists"
|
||||
import { subscription as subscriptionQuery } from "~/queries/subscriptions"
|
||||
|
|
@ -41,6 +39,7 @@ import { feedUnreadActions } from "~/store/unread"
|
|||
|
||||
import { useTOTPModalWrapper } from "../profile/hooks"
|
||||
import { ViewSelectorRadioGroup } from "../shared/ViewSelectorRadioGroup"
|
||||
import { FeedSummary } from "./FeedSummary"
|
||||
|
||||
const formSchema = z.object({
|
||||
view: z.string(),
|
||||
|
|
@ -92,6 +91,7 @@ export const ListForm: Component<{
|
|||
|
||||
onSuccess,
|
||||
subscriptionData: feedQuery.data?.subscription,
|
||||
analytics: feedQuery.data?.analytics,
|
||||
list,
|
||||
}}
|
||||
/>
|
||||
|
|
@ -165,6 +165,7 @@ const ListInnerForm = ({
|
|||
onSuccess,
|
||||
subscriptionData,
|
||||
list,
|
||||
analytics,
|
||||
}: {
|
||||
defaultValues?: z.infer<typeof formSchema>
|
||||
id?: string
|
||||
|
|
@ -177,6 +178,7 @@ const ListInnerForm = ({
|
|||
title?: string | null
|
||||
}
|
||||
list: ListModel
|
||||
analytics?: ListAnalyticsModel
|
||||
}) => {
|
||||
const subscription = useSubscriptionByFeedId(id || "") || subscriptionData
|
||||
const isSubscribed = !!subscription
|
||||
|
|
@ -272,11 +274,7 @@ const ListInnerForm = ({
|
|||
|
||||
return (
|
||||
<div className="flex flex-1 flex-col gap-y-4">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<FollowSummary feed={list} />
|
||||
</CardHeader>
|
||||
</Card>
|
||||
<FeedSummary feed={list} analytics={analytics} showAnalytics />
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-1 flex-col gap-y-4">
|
||||
<FormField
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export function FollowSummary({
|
|||
</EllipsisHorizontalTextWithTooltip>
|
||||
</div>
|
||||
</div>
|
||||
{!simple && (
|
||||
{!simple && feed.description && (
|
||||
<EllipsisHorizontalTextWithTooltip className="text-text/80 text-body truncate pl-10 font-normal">
|
||||
{feed.description}
|
||||
</EllipsisHorizontalTextWithTooltip>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ export type FeedAnalyticsModel = ExtractBizResponse<
|
|||
typeof _apiClient.feeds.$get
|
||||
>["data"]["analytics"]
|
||||
|
||||
export type ListAnalyticsModel = ExtractBizResponse<
|
||||
typeof _apiClient.lists.$get
|
||||
>["data"]["analytics"]
|
||||
|
||||
export type ListModel = Omit<ListModelPoplutedFeeds, "feeds">
|
||||
export type ListModelPoplutedFeeds = ExtractBizResponse<
|
||||
typeof _apiClient.lists.$get
|
||||
|
|
|
|||
|
|
@ -19638,6 +19638,10 @@ declare const _routes: hono_hono_base.HonoBase<Env, ({
|
|||
};
|
||||
readCount: number;
|
||||
feedCount: number;
|
||||
analytics?: {
|
||||
subscriptionCount: number | null;
|
||||
listId: string;
|
||||
} | undefined;
|
||||
subscription?: {
|
||||
createdAt: string;
|
||||
userId: string;
|
||||
|
|
|
|||
Loading…
Reference in New Issue