mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-21 06:13:33 +00:00
130 lines
6.1 KiB
TypeScript
130 lines
6.1 KiB
TypeScript
import classNames from "classnames";
|
|
import { useEffect, useState } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import * as api from "../helpers/api";
|
|
import Icon from "./Icon";
|
|
|
|
interface Props {
|
|
shortcutId: ShortcutId;
|
|
className?: string;
|
|
}
|
|
|
|
const AnalyticsView: React.FC<Props> = (props: Props) => {
|
|
const { shortcutId, className } = props;
|
|
const { t } = useTranslation();
|
|
const [analytics, setAnalytics] = useState<AnalysisData | null>(null);
|
|
const [selectedDeviceTab, setSelectedDeviceTab] = useState<"os" | "browser">("browser");
|
|
|
|
useEffect(() => {
|
|
api.getShortcutAnalytics(shortcutId).then(({ data }) => {
|
|
setAnalytics(data);
|
|
});
|
|
}, []);
|
|
|
|
return (
|
|
<div className={classNames("w-full", className)}>
|
|
{analytics ? (
|
|
<>
|
|
<div className="w-full">
|
|
<p className="w-full h-8 px-2">{t("analytics.top-sources")}</p>
|
|
<div className="w-full mt-1 overflow-hidden shadow ring-1 ring-black ring-opacity-5 rounded-lg">
|
|
<div className="w-full divide-y divide-gray-300">
|
|
<div className="w-full flex flex-row justify-between items-center">
|
|
<span className="py-2 px-2 text-left font-semibold text-sm text-gray-500">{t("analytics.source")}</span>
|
|
<span className="py-2 pr-2 text-right font-semibold text-sm text-gray-500">{t("analytics.visitors")}</span>
|
|
</div>
|
|
<div className="w-full divide-y divide-gray-200">
|
|
{analytics.referenceData.map((reference) => (
|
|
<div key={reference.name} className="w-full flex flex-row justify-between items-center">
|
|
<span className="whitespace-nowrap py-2 px-2 text-sm truncate text-gray-900">
|
|
{reference.name ? (
|
|
<a className="hover:underline hover:text-blue-600" href={reference.name} target="_blank">
|
|
{reference.name}
|
|
</a>
|
|
) : (
|
|
"Direct"
|
|
)}
|
|
</span>
|
|
<span className="whitespace-nowrap py-2 pr-2 text-sm text-gray-500 text-right shrink-0">{reference.count}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="w-full">
|
|
<div className="w-full h-8 px-2 flex flex-row justify-between items-center">
|
|
<span>{t("analytics.devices")}</span>
|
|
<div>
|
|
<button
|
|
className={`whitespace-nowrap border-b-2 px-1 text-sm font-medium ${
|
|
selectedDeviceTab === "browser"
|
|
? "border-blue-600 text-blue-600"
|
|
: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700"
|
|
}`}
|
|
onClick={() => setSelectedDeviceTab("browser")}
|
|
>
|
|
{t("analytics.browser")}
|
|
</button>
|
|
<span className="text-gray-200 font-mono mx-1">/</span>
|
|
<button
|
|
className={`whitespace-nowrap border-b-2 px-1 text-sm font-medium ${
|
|
selectedDeviceTab === "os"
|
|
? "border-blue-600 text-blue-600"
|
|
: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700"
|
|
}`}
|
|
onClick={() => setSelectedDeviceTab("os")}
|
|
>
|
|
OS
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="w-full mt-1 overflow-hidden shadow ring-1 ring-black ring-opacity-5 rounded-lg">
|
|
{selectedDeviceTab === "browser" ? (
|
|
<div className="w-full divide-y divide-gray-300">
|
|
<div className="w-full flex flex-row justify-between items-center">
|
|
<span className="py-2 px-2 text-left text-sm font-semibold text-gray-500">{t("analytics.browsers")}</span>
|
|
<span className="py-2 pr-2 text-right text-sm font-semibold text-gray-500">{t("analytics.visitors")}</span>
|
|
</div>
|
|
<div className="w-full divide-y divide-gray-200">
|
|
{analytics.browserData.map((reference) => (
|
|
<div key={reference.name} className="w-full flex flex-row justify-between items-center">
|
|
<span className="whitespace-nowrap py-2 px-2 text-sm text-gray-900 truncate">{reference.name || "Unknown"}</span>
|
|
<span className="whitespace-nowrap py-2 pr-2 text-sm text-gray-500 text-right shrink-0">{reference.count}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="w-full divide-y divide-gray-300">
|
|
<div className="w-full flex flex-row justify-between items-center">
|
|
<span className="py-2 px-2 text-left text-sm font-semibold text-gray-500">{t("analytics.operating-system")}</span>
|
|
<span className="py-2 pr-2 text-right text-sm font-semibold text-gray-500">{t("analytics.visitors")}</span>
|
|
</div>
|
|
<div className="w-full divide-y divide-gray-200">
|
|
{analytics.deviceData.map((device) => (
|
|
<div key={device.name} className="w-full flex flex-row justify-between items-center">
|
|
<span className="whitespace-nowrap py-2 px-2 text-sm text-gray-900 truncate">{device.name || "Unknown"}</span>
|
|
<span className="whitespace-nowrap py-2 pr-2 text-sm text-gray-500 text-right shrink-0">{device.count}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</>
|
|
) : (
|
|
<div className="py-12 w-full flex flex-row justify-center items-center opacity-80">
|
|
<Icon.Loader className="mr-2 w-5 h-auto animate-spin" />
|
|
{t("common.loading")}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AnalyticsView;
|