@oneclick.dev/cms-core-modules 0.0.79 → 0.0.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AppointmentDetailsCard-Bu9VzIRx.mjs → AppointmentDetailsCard-33WpATpV.mjs} +43 -43
- package/dist/AppointmentDetailsCard-DpLM5IrB.js +1 -0
- package/dist/AppointmentListTable-CQ0WIXtj.js +1 -0
- package/dist/{AppointmentListTable-B8YLwOfT.mjs → AppointmentListTable-aV_UJd6j.mjs} +42 -42
- package/dist/CountryBreakdownCard-D7BK3nRD.js +1 -0
- package/dist/{CountryBreakdownCard-oDzmpvAd.mjs → CountryBreakdownCard-DVxNz2DJ.mjs} +48 -48
- package/dist/DeviceBreakdownCard-DRhQ9ufG.js +1 -0
- package/dist/{DeviceBreakdownCard-Oh_yzipG.mjs → DeviceBreakdownCard-W1frLe0L.mjs} +58 -58
- package/dist/{PeakHoursCard-DzNo4SNo.mjs → PeakHoursCard-9-EZFZLR.mjs} +55 -55
- package/dist/PeakHoursCard-BR5zmta4.js +1 -0
- package/dist/ProductDetailsCard-6nHikw4V.mjs +121 -0
- package/dist/ProductDetailsCard-Bn7qrgmc.js +1 -0
- package/dist/RealtimeCard--APfRNc8.js +1 -0
- package/dist/{RealtimeCard-tNUSIw6B.mjs → RealtimeCard-fvQlJcM7.mjs} +41 -41
- package/dist/SearchTermsCard-BsB-63aH.js +1 -0
- package/dist/{SearchTermsCard-BVHFHWUZ.mjs → SearchTermsCard-BzVrHKqQ.mjs} +57 -57
- package/dist/TopPagesCard-BDeA997A.js +1 -0
- package/dist/{TopPagesCard-CRIa3rSZ.mjs → TopPagesCard-CTozhOr_.mjs} +48 -48
- package/dist/{TrafficSourcesCard-Ct20QYax.mjs → TrafficSourcesCard-BxtCKsqx.mjs} +65 -65
- package/dist/TrafficSourcesCard-C3ziDTUL.js +1 -0
- package/dist/VisitorStatsCard-BmByE_Hi.js +1 -0
- package/dist/{VisitorStatsCard-DMULybKV.mjs → VisitorStatsCard-CXizEbVK.mjs} +55 -55
- package/dist/index.cjs.js +1 -1
- package/dist/index.mjs +11 -11
- package/package.json +2 -2
- package/dist/AppointmentDetailsCard-LL-6PARb.js +0 -1
- package/dist/AppointmentListTable-DNvvb4sz.js +0 -1
- package/dist/CountryBreakdownCard-BpDXbxwZ.js +0 -1
- package/dist/DeviceBreakdownCard-OXiU9Cf0.js +0 -1
- package/dist/PeakHoursCard-OkgI1vnd.js +0 -1
- package/dist/ProductDetailsCard-BBOorNmB.js +0 -1
- package/dist/ProductDetailsCard-CYK9Mtt4.mjs +0 -121
- package/dist/RealtimeCard-DESm9Fs_.js +0 -1
- package/dist/SearchTermsCard-DmyhGQVM.js +0 -1
- package/dist/TopPagesCard-CgtNyhwY.js +0 -1
- package/dist/TrafficSourcesCard-CPAxaQTi.js +0 -1
- package/dist/VisitorStatsCard-Cs6jPehw.js +0 -1
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import { Loader2 as
|
|
3
|
-
const
|
|
1
|
+
import { defineComponent as C, computed as S, ref as m, onMounted as P, resolveComponent as V, openBlock as n, createElementBlock as o, unref as a, createVNode as i, createElementVNode as e, toDisplayString as r, Fragment as $, renderList as D, createCommentVNode as _, withCtx as E, createTextVNode as F } from "vue";
|
|
2
|
+
import { Loader2 as I, Radio as M, Users as h, ExternalLink as T } from "lucide-vue-next";
|
|
3
|
+
const B = { class: "w-full" }, O = {
|
|
4
4
|
key: 0,
|
|
5
5
|
class: "flex items-center gap-2 py-3"
|
|
6
|
-
},
|
|
6
|
+
}, q = {
|
|
7
7
|
key: 1,
|
|
8
8
|
class: "text-xs text-destructive py-2"
|
|
9
|
-
},
|
|
9
|
+
}, G = {
|
|
10
10
|
key: 2,
|
|
11
11
|
class: "rounded-xl border bg-background overflow-hidden"
|
|
12
|
-
},
|
|
12
|
+
}, H = { class: "px-3 py-2 border-b bg-muted/40 flex items-center justify-between" }, J = { class: "flex items-center gap-2" }, K = { class: "px-3 py-4 text-center" }, Q = { class: "flex items-center justify-center gap-2 mb-1" }, W = { class: "text-3xl font-bold" }, X = { class: "text-xs text-muted-foreground" }, Y = {
|
|
13
13
|
key: 0,
|
|
14
14
|
class: "border-t"
|
|
15
|
-
},
|
|
15
|
+
}, Z = { class: "divide-y" }, ee = ["title"], te = { class: "flex items-center gap-1 text-[10px] text-muted-foreground shrink-0 ml-2" }, se = { class: "font-medium" }, ae = { class: "px-3 py-2 border-t bg-muted/20 flex items-center justify-between" }, ne = {
|
|
16
16
|
key: 0,
|
|
17
17
|
class: "text-[10px] text-muted-foreground"
|
|
18
|
-
}, re = /* @__PURE__ */
|
|
18
|
+
}, re = /* @__PURE__ */ C({
|
|
19
19
|
__name: "RealtimeCard",
|
|
20
20
|
props: {
|
|
21
21
|
toolName: {},
|
|
@@ -27,18 +27,18 @@ const T = { class: "w-full" }, B = {
|
|
|
27
27
|
},
|
|
28
28
|
emits: ["submit"],
|
|
29
29
|
setup(v, { emit: y }) {
|
|
30
|
-
const { $useRoute: b, $
|
|
31
|
-
function
|
|
30
|
+
const { $useRoute: b, $useModuleApi: w } = useNuxtApp(), l = v, k = y, N = b(), A = S(() => N.params.slug), U = w(l.instanceId), p = m(!0), d = m(null), c = m(0), u = m([]), x = m(null);
|
|
31
|
+
function z() {
|
|
32
32
|
const s = l.resolvedArgs?._cachedData;
|
|
33
33
|
return s ? (c.value = s.activeUsersRightNow || 0, u.value = (s.topActivePages || []).map((t) => ({
|
|
34
34
|
page: t.page,
|
|
35
35
|
activeUsers: t.activeUsers
|
|
36
36
|
})), x.value = l.resolvedArgs._fetchedAt || null, p.value = !1, !0) : !1;
|
|
37
37
|
}
|
|
38
|
-
async function
|
|
38
|
+
async function L() {
|
|
39
39
|
p.value = !0, d.value = null;
|
|
40
40
|
try {
|
|
41
|
-
const s = await
|
|
41
|
+
const s = await U.get("/realtime");
|
|
42
42
|
c.value = s.activeUsers || 0, u.value = s.activePages || [], x.value = (/* @__PURE__ */ new Date()).toISOString(), g({
|
|
43
43
|
activeUsersRightNow: c.value,
|
|
44
44
|
topActivePages: u.value.map((t) => ({
|
|
@@ -52,23 +52,23 @@ const T = { class: "w-full" }, B = {
|
|
|
52
52
|
p.value = !1;
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
|
|
56
|
-
l.status === "completed" &&
|
|
55
|
+
P(() => {
|
|
56
|
+
l.status === "completed" && z() || L();
|
|
57
57
|
});
|
|
58
58
|
function g(s) {
|
|
59
|
-
l.status !== "completed" &&
|
|
59
|
+
l.status !== "completed" && k("submit", s);
|
|
60
60
|
}
|
|
61
|
-
const
|
|
61
|
+
const R = (s) => s ? new Date(s).toLocaleString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }) : "";
|
|
62
62
|
return (s, t) => {
|
|
63
|
-
const
|
|
64
|
-
return
|
|
65
|
-
a(p) ? (
|
|
66
|
-
i(a(
|
|
63
|
+
const j = V("NuxtLink");
|
|
64
|
+
return n(), o("div", B, [
|
|
65
|
+
a(p) ? (n(), o("div", O, [
|
|
66
|
+
i(a(I), { class: "size-4 animate-spin text-muted-foreground" }),
|
|
67
67
|
t[0] || (t[0] = e("span", { class: "text-xs text-muted-foreground" }, "Loading realtime data…", -1))
|
|
68
|
-
])) : a(d) ? (
|
|
69
|
-
e("div",
|
|
70
|
-
e("div",
|
|
71
|
-
i(a(
|
|
68
|
+
])) : a(d) ? (n(), o("div", q, r(a(d)), 1)) : (n(), o("div", G, [
|
|
69
|
+
e("div", H, [
|
|
70
|
+
e("div", J, [
|
|
71
|
+
i(a(M), { class: "size-3.5 text-emerald-500" }),
|
|
72
72
|
t[1] || (t[1] = e("span", { class: "text-xs font-medium" }, "Realtime", -1))
|
|
73
73
|
]),
|
|
74
74
|
t[2] || (t[2] = e("span", { class: "relative flex size-2" }, [
|
|
@@ -76,42 +76,42 @@ const T = { class: "w-full" }, B = {
|
|
|
76
76
|
e("span", { class: "relative inline-flex rounded-full size-2 bg-emerald-500" })
|
|
77
77
|
], -1))
|
|
78
78
|
]),
|
|
79
|
-
e("div",
|
|
80
|
-
e("div",
|
|
79
|
+
e("div", K, [
|
|
80
|
+
e("div", Q, [
|
|
81
81
|
i(a(h), { class: "size-5 text-primary" }),
|
|
82
|
-
e("span",
|
|
82
|
+
e("span", W, r(a(c)), 1)
|
|
83
83
|
]),
|
|
84
|
-
e("p",
|
|
84
|
+
e("p", X, "active " + r(a(c) === 1 ? "user" : "users") + " right now", 1)
|
|
85
85
|
]),
|
|
86
|
-
a(u).length > 0 ? (
|
|
86
|
+
a(u).length > 0 ? (n(), o("div", Y, [
|
|
87
87
|
t[3] || (t[3] = e("div", { class: "px-3 py-1.5 bg-muted/20" }, [
|
|
88
88
|
e("span", { class: "text-[10px] font-medium text-muted-foreground uppercase tracking-wide" }, "Active Pages")
|
|
89
89
|
], -1)),
|
|
90
|
-
e("div",
|
|
91
|
-
(
|
|
90
|
+
e("div", Z, [
|
|
91
|
+
(n(!0), o($, null, D(a(u), (f) => (n(), o("div", {
|
|
92
92
|
key: f.page,
|
|
93
93
|
class: "px-3 py-2 flex items-center justify-between hover:bg-muted/30 transition-colors"
|
|
94
94
|
}, [
|
|
95
95
|
e("span", {
|
|
96
96
|
class: "text-xs truncate flex-1",
|
|
97
97
|
title: f.page
|
|
98
|
-
}, r(f.page), 9,
|
|
99
|
-
e("div",
|
|
98
|
+
}, r(f.page), 9, ee),
|
|
99
|
+
e("div", te, [
|
|
100
100
|
i(a(h), { class: "size-2.5" }),
|
|
101
|
-
e("span",
|
|
101
|
+
e("span", se, r(f.activeUsers), 1)
|
|
102
102
|
])
|
|
103
103
|
]))), 128))
|
|
104
104
|
])
|
|
105
105
|
])) : _("", !0),
|
|
106
|
-
e("div",
|
|
107
|
-
a(x) ? (
|
|
108
|
-
i(
|
|
109
|
-
to: `/projects/${a(
|
|
106
|
+
e("div", ae, [
|
|
107
|
+
a(x) ? (n(), o("span", ne, " Fetched " + r(R(a(x))), 1)) : _("", !0),
|
|
108
|
+
i(j, {
|
|
109
|
+
to: `/projects/${a(A)}/modules/${v.instanceId}`,
|
|
110
110
|
class: "inline-flex items-center gap-1.5 text-xs text-primary hover:underline"
|
|
111
111
|
}, {
|
|
112
|
-
default:
|
|
113
|
-
i(a(
|
|
114
|
-
t[4] || (t[4] =
|
|
112
|
+
default: E(() => [
|
|
113
|
+
i(a(T), { class: "size-3" }),
|
|
114
|
+
t[4] || (t[4] = F(" View full report ", -1))
|
|
115
115
|
]),
|
|
116
116
|
_: 1
|
|
117
117
|
}, 8, ["to"])
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),c=require("lucide-vue-next"),M={class:"w-full"},R={key:0,class:"flex items-center gap-2 py-3"},U={key:1,class:"text-xs text-destructive py-2"},j={key:2,class:"rounded-xl border bg-background p-4 text-center space-y-2"},q={key:3,class:"rounded-xl border bg-background overflow-hidden"},G={class:"px-3 py-2 border-b bg-muted/40 flex items-center justify-between"},I={class:"flex items-center gap-2"},Q={class:"text-xs font-medium"},K={class:"text-[10px] text-muted-foreground"},O={class:"divide-y"},H={class:"flex items-center gap-2 mb-1.5"},J={class:"text-[10px] font-medium text-muted-foreground w-5 text-right shrink-0"},W={class:"text-xs font-medium truncate flex-1"},X={class:"ml-7 space-y-1.5"},Y={class:"h-1.5 rounded-full bg-muted overflow-hidden"},Z={key:0,class:"flex items-center gap-3 text-[10px] text-muted-foreground"},ee={class:"flex items-center gap-1"},te={class:"flex items-center gap-1"},se={class:"flex items-center gap-1"},oe={class:"flex items-center gap-1"},ne={key:1,class:"flex items-center gap-3 text-[10px] text-muted-foreground"},re={class:"flex items-center gap-1"},ae={class:"flex items-center gap-1"},ce={class:"flex items-center gap-1"},le={class:"px-3 py-2 border-t bg-muted/20 flex items-center justify-between"},ie={class:"text-[10px] text-muted-foreground"},de=e.defineComponent({__name:"SearchTermsCard",props:{toolName:{},instanceId:{},instanceName:{},moduleType:{},resolvedArgs:{},status:{}},emits:["submit"],setup(x,{emit:N}){const{$useRoute:V,$useModuleApi:k}=useNuxtApp(),i=x,S=N,b=V(),E=e.computed(()=>b.params.slug),T=k(i.instanceId),m=e.ref(!0),d=e.ref(null),o=e.ref([]),_=e.ref(0),g=e.ref(null),u=e.ref("google_ads"),D=t=>t.label||t.query||t.sessionGoogleAdsQuery||t.landingPagePlusQueryString||"—";function B(){const t=i.resolvedArgs?._cachedData;return t?(u.value=t.source||"google_ads",t.source==="search_console"?o.value=(t.searchTerms||[]).map(s=>({label:s.term,clicks:s.clicks,impressions:s.impressions,ctr:s.ctr,position:s.position})):o.value=(t.searchTerms||[]).map(s=>({label:s.term,sessions:s.sessions,totalUsers:s.users,engagementRate:parseFloat(s.engagementRate)/100})),_.value=t.count||o.value.length,g.value=i.resolvedArgs._fetchedAt||null,m.value=!1,!0):!1}async function $(){const{startDate:t,endDate:s}=i.resolvedArgs||{};m.value=!0,d.value=null;try{const a=new URLSearchParams;t&&a.set("startDate",t),s&&a.set("endDate",s);const n=await T.get(`/content/search-terms?${a.toString()}`),l=n.source||"google_ads";if(u.value=l,l==="search_console")o.value=(n.rows||[]).map(r=>({...r,label:r.query}));else{const r=l==="organic_landing_pages"?"landingPagePlusQueryString":"sessionGoogleAdsQuery";o.value=(n.rows||[]).map(f=>({...f,label:f[r]}))}_.value=n.rowCount||o.value.length,g.value=new Date().toISOString();const F=()=>{if(o.value.length===0)return"No search data found for this period.";const r=o.value.slice(0,5).map(f=>f.label).join(", ");return l==="search_console"?`Found ${o.value.length} search queries from Google Search Console. The top keywords are: ${r}.`:l==="organic_landing_pages"?`Found ${o.value.length} pages receiving organic search traffic. The top organic landing pages are: ${r}.`:`Found ${o.value.length} search terms. The top keywords driving traffic are: ${r}.`},P=o.value.map(r=>l==="search_console"?{term:r.label,clicks:r.clicks,impressions:r.impressions,ctr:r.ctr,position:r.position}:{term:r.label,sessions:r.sessions,users:r.totalUsers,engagementRate:`${(r.engagementRate*100).toFixed(1)}%`});v({count:o.value.length,source:l,searchTerms:P,suggestion:F()})}catch(a){d.value=a?.data?.statusMessage||a?.message||"Failed to load search data",v(`Error loading search data: ${d.value}`)}finally{m.value=!1}}e.onMounted(()=>{i.status==="completed"&&B()||$()});function v(t){i.status!=="completed"&&S("submit",t)}const p=t=>t==null?"0":Math.round(t).toLocaleString(),y=t=>t==null?"0%":`${(t*100).toFixed(1)}%`,w=t=>t==null?"—":t.toFixed(1),C=t=>t?new Date(t).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}):"",h=e.computed(()=>u.value==="search_console"),L=e.computed(()=>o.value.length===0?1:h.value?Math.max(...o.value.map(t=>t.clicks||0)):Math.max(...o.value.map(t=>t.sessions||0))),A=e.computed(()=>u.value==="search_console"?"Search Keywords (Search Console)":u.value==="organic_landing_pages"?"Top Organic Landing Pages":"Search Terms & Keywords"),z=e.computed(()=>{const{startDate:t,endDate:s}=i.resolvedArgs||{};if(!t&&!s)return"Last 30 days";const a=t||"30daysAgo",n=a.match(/^(\d+)daysAgo$/);return n?`Last ${n[1]} days`:`${a} → ${s||"today"}`});return(t,s)=>{const a=e.resolveComponent("NuxtLink");return e.openBlock(),e.createElementBlock("div",M,[e.unref(m)?(e.openBlock(),e.createElementBlock("div",R,[e.createVNode(e.unref(c.Loader2),{class:"size-4 animate-spin text-muted-foreground"}),s[0]||(s[0]=e.createElementVNode("span",{class:"text-xs text-muted-foreground"},"Loading search data…",-1))])):e.unref(d)?(e.openBlock(),e.createElementBlock("div",U,e.toDisplayString(e.unref(d)),1)):e.unref(o).length===0?(e.openBlock(),e.createElementBlock("div",j,[e.createVNode(e.unref(c.Search),{class:"size-8 text-muted-foreground mx-auto"}),s[1]||(s[1]=e.createElementVNode("p",{class:"text-sm text-muted-foreground"},"No search data found for this period.",-1))])):(e.openBlock(),e.createElementBlock("div",q,[e.createElementVNode("div",G,[e.createElementVNode("div",I,[e.createVNode(e.unref(c.Search),{class:"size-3.5 text-primary"}),e.createElementVNode("span",Q,e.toDisplayString(e.unref(A)),1)]),e.createElementVNode("span",K,e.toDisplayString(e.unref(z)),1)]),e.createElementVNode("div",O,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(o),(n,l)=>(e.openBlock(),e.createElementBlock("div",{key:l,class:"px-3 py-2.5 hover:bg-muted/30 transition-colors"},[e.createElementVNode("div",H,[e.createElementVNode("span",J,e.toDisplayString(l+1)+".",1),e.createElementVNode("span",W,e.toDisplayString(D(n)),1)]),e.createElementVNode("div",X,[e.createElementVNode("div",Y,[e.createElementVNode("div",{class:"h-full rounded-full bg-amber-500/70 transition-all",style:e.normalizeStyle({width:`${((e.unref(h)?n.clicks:n.sessions)||0)/e.unref(L)*100}%`})},null,4)]),e.unref(h)?(e.openBlock(),e.createElementBlock("div",Z,[e.createElementVNode("span",ee,[e.createVNode(e.unref(c.MousePointerClick),{class:"size-2.5"}),e.createTextVNode(" "+e.toDisplayString(p(n.clicks))+" clicks ",1)]),e.createElementVNode("span",te,[e.createVNode(e.unref(c.Eye),{class:"size-2.5"}),e.createTextVNode(" "+e.toDisplayString(p(n.impressions))+" impr. ",1)]),e.createElementVNode("span",se,[e.createVNode(e.unref(c.TrendingUp),{class:"size-2.5"}),e.createTextVNode(" "+e.toDisplayString(y(n.ctr))+" CTR ",1)]),e.createElementVNode("span",oe,[e.createVNode(e.unref(c.Hash),{class:"size-2.5"}),e.createTextVNode(" pos "+e.toDisplayString(w(n.position)),1)])])):(e.openBlock(),e.createElementBlock("div",ne,[e.createElementVNode("span",re,[e.createVNode(e.unref(c.MousePointerClick),{class:"size-2.5"}),e.createTextVNode(" "+e.toDisplayString(p(n.sessions))+" sessions ",1)]),e.createElementVNode("span",ae,[e.createVNode(e.unref(c.Users),{class:"size-2.5"}),e.createTextVNode(" "+e.toDisplayString(p(n.totalUsers))+" users ",1)]),e.createElementVNode("span",ce,[e.createVNode(e.unref(c.TrendingUp),{class:"size-2.5"}),e.createTextVNode(" "+e.toDisplayString(y(n.engagementRate))+" engaged ",1)])]))])]))),128))]),e.createElementVNode("div",le,[e.createElementVNode("span",ie,[e.createTextVNode(e.toDisplayString(e.unref(o).length)+" result"+e.toDisplayString(e.unref(o).length===1?"":"s")+" ",1),e.unref(g)?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createTextVNode(" · fetched "+e.toDisplayString(C(e.unref(g))),1)],64)):e.createCommentVNode("",!0)]),e.createVNode(a,{to:`/projects/${e.unref(E)}/modules/${x.instanceId}`,class:"inline-flex items-center gap-1.5 text-xs text-primary hover:underline"},{default:e.withCtx(()=>[e.createVNode(e.unref(c.ExternalLink),{class:"size-3"}),s[2]||(s[2]=e.createTextVNode(" View full report ",-1))]),_:1},8,["to"])])]))])}}});exports.default=de;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import { Loader2 as
|
|
3
|
-
const
|
|
1
|
+
import { defineComponent as J, computed as _, ref as h, onMounted as W, resolveComponent as X, openBlock as u, createElementBlock as m, unref as s, createVNode as l, createElementVNode as o, toDisplayString as i, Fragment as A, renderList as Y, normalizeStyle as Z, createTextVNode as g, createCommentVNode as ee, withCtx as se } from "vue";
|
|
2
|
+
import { Loader2 as te, Search as C, MousePointerClick as z, Eye as oe, TrendingUp as N, Hash as ne, Users as ae, ExternalLink as re } from "lucide-vue-next";
|
|
3
|
+
const ie = { class: "w-full" }, le = {
|
|
4
4
|
key: 0,
|
|
5
5
|
class: "flex items-center gap-2 py-3"
|
|
6
|
-
},
|
|
6
|
+
}, ce = {
|
|
7
7
|
key: 1,
|
|
8
8
|
class: "text-xs text-destructive py-2"
|
|
9
|
-
},
|
|
9
|
+
}, de = {
|
|
10
10
|
key: 2,
|
|
11
11
|
class: "rounded-xl border bg-background p-4 text-center space-y-2"
|
|
12
|
-
},
|
|
12
|
+
}, ue = {
|
|
13
13
|
key: 3,
|
|
14
14
|
class: "rounded-xl border bg-background overflow-hidden"
|
|
15
|
-
},
|
|
15
|
+
}, me = { class: "px-3 py-2 border-b bg-muted/40 flex items-center justify-between" }, ge = { class: "flex items-center gap-2" }, pe = { class: "text-xs font-medium" }, he = { class: "text-[10px] text-muted-foreground" }, fe = { class: "divide-y" }, xe = { class: "flex items-center gap-2 mb-1.5" }, _e = { class: "text-[10px] font-medium text-muted-foreground w-5 text-right shrink-0" }, ve = { class: "text-xs font-medium truncate flex-1" }, ye = { class: "ml-7 space-y-1.5" }, be = { class: "h-1.5 rounded-full bg-muted overflow-hidden" }, ke = {
|
|
16
16
|
key: 0,
|
|
17
17
|
class: "flex items-center gap-3 text-[10px] text-muted-foreground"
|
|
18
|
-
},
|
|
18
|
+
}, Se = { class: "flex items-center gap-1" }, $e = { class: "flex items-center gap-1" }, Te = { class: "flex items-center gap-1" }, we = { class: "flex items-center gap-1" }, Le = {
|
|
19
19
|
key: 1,
|
|
20
20
|
class: "flex items-center gap-3 text-[10px] text-muted-foreground"
|
|
21
|
-
},
|
|
21
|
+
}, Ae = { class: "flex items-center gap-1" }, Ce = { class: "flex items-center gap-1" }, ze = { class: "flex items-center gap-1" }, Ne = { class: "px-3 py-2 border-t bg-muted/20 flex items-center justify-between" }, De = { class: "text-[10px] text-muted-foreground" }, Me = /* @__PURE__ */ J({
|
|
22
22
|
__name: "SearchTermsCard",
|
|
23
23
|
props: {
|
|
24
24
|
toolName: {},
|
|
@@ -30,8 +30,8 @@ const re = { class: "w-full" }, ie = {
|
|
|
30
30
|
},
|
|
31
31
|
emits: ["submit"],
|
|
32
32
|
setup($, { emit: D }) {
|
|
33
|
-
const { $useRoute: F, $
|
|
34
|
-
function
|
|
33
|
+
const { $useRoute: F, $useModuleApi: P } = useNuxtApp(), p = $, M = D, R = F(), U = _(() => R.params.slug), j = P(p.instanceId), v = h(!0), f = h(null), n = h([]), T = h(0), y = h(null), x = h("google_ads"), E = (e) => e.label || e.query || e.sessionGoogleAdsQuery || e.landingPagePlusQueryString || "—";
|
|
34
|
+
function V() {
|
|
35
35
|
const e = p.resolvedArgs?._cachedData;
|
|
36
36
|
return e ? (x.value = e.source || "google_ads", e.source === "search_console" ? n.value = (e.searchTerms || []).map((t) => ({
|
|
37
37
|
label: t.term,
|
|
@@ -46,13 +46,13 @@ const re = { class: "w-full" }, ie = {
|
|
|
46
46
|
engagementRate: parseFloat(t.engagementRate) / 100
|
|
47
47
|
})), T.value = e.count || n.value.length, y.value = p.resolvedArgs._fetchedAt || null, v.value = !1, !0) : !1;
|
|
48
48
|
}
|
|
49
|
-
async function
|
|
49
|
+
async function G() {
|
|
50
50
|
const { startDate: e, endDate: t } = p.resolvedArgs || {};
|
|
51
51
|
v.value = !0, f.value = null;
|
|
52
52
|
try {
|
|
53
53
|
const c = new URLSearchParams();
|
|
54
54
|
e && c.set("startDate", e), t && c.set("endDate", t);
|
|
55
|
-
const a = await
|
|
55
|
+
const a = await j.get(`/content/search-terms?${c.toString()}`), d = a.source || "google_ads";
|
|
56
56
|
if (x.value = d, d === "search_console")
|
|
57
57
|
n.value = (a.rows || []).map((r) => ({
|
|
58
58
|
...r,
|
|
@@ -70,7 +70,7 @@ const re = { class: "w-full" }, ie = {
|
|
|
70
70
|
if (n.value.length === 0) return "No search data found for this period.";
|
|
71
71
|
const r = n.value.slice(0, 5).map((k) => k.label).join(", ");
|
|
72
72
|
return d === "search_console" ? `Found ${n.value.length} search queries from Google Search Console. The top keywords are: ${r}.` : d === "organic_landing_pages" ? `Found ${n.value.length} pages receiving organic search traffic. The top organic landing pages are: ${r}.` : `Found ${n.value.length} search terms. The top keywords driving traffic are: ${r}.`;
|
|
73
|
-
},
|
|
73
|
+
}, H = n.value.map((r) => d === "search_console" ? {
|
|
74
74
|
term: r.label,
|
|
75
75
|
clicks: r.clicks,
|
|
76
76
|
impressions: r.impressions,
|
|
@@ -85,7 +85,7 @@ const re = { class: "w-full" }, ie = {
|
|
|
85
85
|
w({
|
|
86
86
|
count: n.value.length,
|
|
87
87
|
source: d,
|
|
88
|
-
searchTerms:
|
|
88
|
+
searchTerms: H,
|
|
89
89
|
suggestion: O()
|
|
90
90
|
});
|
|
91
91
|
} catch (c) {
|
|
@@ -94,78 +94,78 @@ const re = { class: "w-full" }, ie = {
|
|
|
94
94
|
v.value = !1;
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
p.status === "completed" &&
|
|
97
|
+
W(() => {
|
|
98
|
+
p.status === "completed" && V() || G();
|
|
99
99
|
});
|
|
100
100
|
function w(e) {
|
|
101
101
|
p.status !== "completed" && M("submit", e);
|
|
102
102
|
}
|
|
103
|
-
const b = (e) => e == null ? "0" : Math.round(e).toLocaleString(), L = (e) => e == null ? "0%" : `${(e * 100).toFixed(1)}%`,
|
|
103
|
+
const b = (e) => e == null ? "0" : Math.round(e).toLocaleString(), L = (e) => e == null ? "0%" : `${(e * 100).toFixed(1)}%`, I = (e) => e == null ? "—" : e.toFixed(1), Q = (e) => e ? new Date(e).toLocaleString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }) : "", S = _(() => x.value === "search_console"), q = _(() => n.value.length === 0 ? 1 : S.value ? Math.max(...n.value.map((e) => e.clicks || 0)) : Math.max(...n.value.map((e) => e.sessions || 0))), K = _(() => x.value === "search_console" ? "Search Keywords (Search Console)" : x.value === "organic_landing_pages" ? "Top Organic Landing Pages" : "Search Terms & Keywords"), B = _(() => {
|
|
104
104
|
const { startDate: e, endDate: t } = p.resolvedArgs || {};
|
|
105
105
|
if (!e && !t) return "Last 30 days";
|
|
106
106
|
const c = e || "30daysAgo", a = c.match(/^(\d+)daysAgo$/);
|
|
107
107
|
return a ? `Last ${a[1]} days` : `${c} → ${t || "today"}`;
|
|
108
108
|
});
|
|
109
109
|
return (e, t) => {
|
|
110
|
-
const c =
|
|
111
|
-
return u(), m("div",
|
|
112
|
-
s(v) ? (u(), m("div",
|
|
113
|
-
l(s(
|
|
110
|
+
const c = X("NuxtLink");
|
|
111
|
+
return u(), m("div", ie, [
|
|
112
|
+
s(v) ? (u(), m("div", le, [
|
|
113
|
+
l(s(te), { class: "size-4 animate-spin text-muted-foreground" }),
|
|
114
114
|
t[0] || (t[0] = o("span", { class: "text-xs text-muted-foreground" }, "Loading search data…", -1))
|
|
115
|
-
])) : s(f) ? (u(), m("div",
|
|
115
|
+
])) : s(f) ? (u(), m("div", ce, i(s(f)), 1)) : s(n).length === 0 ? (u(), m("div", de, [
|
|
116
116
|
l(s(C), { class: "size-8 text-muted-foreground mx-auto" }),
|
|
117
117
|
t[1] || (t[1] = o("p", { class: "text-sm text-muted-foreground" }, "No search data found for this period.", -1))
|
|
118
|
-
])) : (u(), m("div",
|
|
119
|
-
o("div",
|
|
120
|
-
o("div",
|
|
118
|
+
])) : (u(), m("div", ue, [
|
|
119
|
+
o("div", me, [
|
|
120
|
+
o("div", ge, [
|
|
121
121
|
l(s(C), { class: "size-3.5 text-primary" }),
|
|
122
|
-
o("span",
|
|
122
|
+
o("span", pe, i(s(K)), 1)
|
|
123
123
|
]),
|
|
124
|
-
o("span",
|
|
124
|
+
o("span", he, i(s(B)), 1)
|
|
125
125
|
]),
|
|
126
|
-
o("div",
|
|
127
|
-
(u(!0), m(A, null,
|
|
126
|
+
o("div", fe, [
|
|
127
|
+
(u(!0), m(A, null, Y(s(n), (a, d) => (u(), m("div", {
|
|
128
128
|
key: d,
|
|
129
129
|
class: "px-3 py-2.5 hover:bg-muted/30 transition-colors"
|
|
130
130
|
}, [
|
|
131
|
-
o("div",
|
|
132
|
-
o("span",
|
|
133
|
-
o("span",
|
|
131
|
+
o("div", xe, [
|
|
132
|
+
o("span", _e, i(d + 1) + ".", 1),
|
|
133
|
+
o("span", ve, i(E(a)), 1)
|
|
134
134
|
]),
|
|
135
|
-
o("div",
|
|
136
|
-
o("div",
|
|
135
|
+
o("div", ye, [
|
|
136
|
+
o("div", be, [
|
|
137
137
|
o("div", {
|
|
138
138
|
class: "h-full rounded-full bg-amber-500/70 transition-all",
|
|
139
|
-
style:
|
|
139
|
+
style: Z({ width: `${((s(S) ? a.clicks : a.sessions) || 0) / s(q) * 100}%` })
|
|
140
140
|
}, null, 4)
|
|
141
141
|
]),
|
|
142
|
-
s(S) ? (u(), m("div",
|
|
143
|
-
o("span",
|
|
142
|
+
s(S) ? (u(), m("div", ke, [
|
|
143
|
+
o("span", Se, [
|
|
144
144
|
l(s(z), { class: "size-2.5" }),
|
|
145
145
|
g(" " + i(b(a.clicks)) + " clicks ", 1)
|
|
146
146
|
]),
|
|
147
|
-
o("span",
|
|
148
|
-
l(s(
|
|
147
|
+
o("span", $e, [
|
|
148
|
+
l(s(oe), { class: "size-2.5" }),
|
|
149
149
|
g(" " + i(b(a.impressions)) + " impr. ", 1)
|
|
150
150
|
]),
|
|
151
|
-
o("span",
|
|
151
|
+
o("span", Te, [
|
|
152
152
|
l(s(N), { class: "size-2.5" }),
|
|
153
153
|
g(" " + i(L(a.ctr)) + " CTR ", 1)
|
|
154
154
|
]),
|
|
155
|
-
o("span",
|
|
156
|
-
l(s(
|
|
157
|
-
g(" pos " + i(
|
|
155
|
+
o("span", we, [
|
|
156
|
+
l(s(ne), { class: "size-2.5" }),
|
|
157
|
+
g(" pos " + i(I(a.position)), 1)
|
|
158
158
|
])
|
|
159
|
-
])) : (u(), m("div",
|
|
160
|
-
o("span",
|
|
159
|
+
])) : (u(), m("div", Le, [
|
|
160
|
+
o("span", Ae, [
|
|
161
161
|
l(s(z), { class: "size-2.5" }),
|
|
162
162
|
g(" " + i(b(a.sessions)) + " sessions ", 1)
|
|
163
163
|
]),
|
|
164
|
-
o("span",
|
|
165
|
-
l(s(
|
|
164
|
+
o("span", Ce, [
|
|
165
|
+
l(s(ae), { class: "size-2.5" }),
|
|
166
166
|
g(" " + i(b(a.totalUsers)) + " users ", 1)
|
|
167
167
|
]),
|
|
168
|
-
o("span",
|
|
168
|
+
o("span", ze, [
|
|
169
169
|
l(s(N), { class: "size-2.5" }),
|
|
170
170
|
g(" " + i(L(a.engagementRate)) + " engaged ", 1)
|
|
171
171
|
])
|
|
@@ -173,19 +173,19 @@ const re = { class: "w-full" }, ie = {
|
|
|
173
173
|
])
|
|
174
174
|
]))), 128))
|
|
175
175
|
]),
|
|
176
|
-
o("div",
|
|
177
|
-
o("span",
|
|
176
|
+
o("div", Ne, [
|
|
177
|
+
o("span", De, [
|
|
178
178
|
g(i(s(n).length) + " result" + i(s(n).length === 1 ? "" : "s") + " ", 1),
|
|
179
179
|
s(y) ? (u(), m(A, { key: 0 }, [
|
|
180
|
-
g(" · fetched " + i(
|
|
181
|
-
], 64)) :
|
|
180
|
+
g(" · fetched " + i(Q(s(y))), 1)
|
|
181
|
+
], 64)) : ee("", !0)
|
|
182
182
|
]),
|
|
183
183
|
l(c, {
|
|
184
|
-
to: `/projects/${s(
|
|
184
|
+
to: `/projects/${s(U)}/modules/${$.instanceId}`,
|
|
185
185
|
class: "inline-flex items-center gap-1.5 text-xs text-primary hover:underline"
|
|
186
186
|
}, {
|
|
187
|
-
default:
|
|
188
|
-
l(s(
|
|
187
|
+
default: se(() => [
|
|
188
|
+
l(s(re), { class: "size-3" }),
|
|
189
189
|
t[2] || (t[2] = g(" View full report ", -1))
|
|
190
190
|
]),
|
|
191
191
|
_: 1
|
|
@@ -197,5 +197,5 @@ const re = { class: "w-full" }, ie = {
|
|
|
197
197
|
}
|
|
198
198
|
});
|
|
199
199
|
export {
|
|
200
|
-
|
|
200
|
+
Me as default
|
|
201
201
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),c=require("lucide-vue-next"),T={class:"w-full"},$={key:0,class:"flex items-center gap-2 py-3"},L={key:1,class:"text-xs text-destructive py-2"},A={key:2,class:"rounded-xl border bg-background p-4 text-center"},M={key:3,class:"rounded-xl border bg-background overflow-hidden"},C={class:"px-3 py-2 border-b bg-muted/40 flex items-center justify-between"},z={class:"flex items-center gap-2"},F={class:"text-[10px] text-muted-foreground"},I={class:"divide-y"},j={class:"flex items-center gap-2 mb-1.5"},U={class:"text-[10px] font-medium text-muted-foreground w-5 text-right shrink-0"},q=["title"],O={class:"ml-7 space-y-1.5"},R={class:"h-1.5 rounded-full bg-muted overflow-hidden"},G={class:"flex items-center gap-3 text-[10px] text-muted-foreground"},H={class:"flex items-center gap-1"},J={class:"flex items-center gap-1"},K={class:"flex items-center gap-1"},Q={class:"px-3 py-2 border-t bg-muted/20 flex items-center justify-between"},W={class:"text-[10px] text-muted-foreground"},X=e.defineComponent({__name:"TopPagesCard",props:{toolName:{},instanceId:{},instanceName:{},moduleType:{},resolvedArgs:{},status:{}},emits:["submit"],setup(f,{emit:h}){const{$useRoute:y,$useModuleApi:N}=useNuxtApp(),l=f,V=h,_=y(),k=e.computed(()=>_.params.slug),E=N(l.instanceId),d=e.ref(!0),i=e.ref(null),a=e.ref([]),u=e.ref(0),m=e.ref(null);function b(){const t=l.resolvedArgs?._cachedData;return t?(a.value=t.pages?.map(s=>({pagePath:s.page,screenPageViews:s.views,totalUsers:s.users,averageSessionDuration:D(s.avgDuration)}))||[],u.value=t.totalPagesTracked||a.value.length,m.value=l.resolvedArgs._fetchedAt||null,d.value=!1,!0):!1}function D(t){if(!t)return 0;const s=t.match(/(\d+)m/),n=t.match(/(\d+)s/);return(s?parseInt(s[1])*60:0)+(n?parseInt(n[1]):0)}async function w(){const{startDate:t,endDate:s,limit:n}=l.resolvedArgs||{};d.value=!0,i.value=null;try{const o=new URLSearchParams;t&&o.set("startDate",t),s&&o.set("endDate",s),n&&o.set("limit",String(n));const r=await E.get(`/top-pages?${o.toString()}`);a.value=r.rows||[],u.value=r.rowCount||a.value.length,m.value=new Date().toISOString(),x({count:a.value.length,totalPagesTracked:u.value,pages:a.value.map(p=>({page:p.pagePath,views:p.screenPageViews,users:p.totalUsers,avgDuration:v(p.averageSessionDuration)}))})}catch(o){i.value=o?.data?.statusMessage||o?.message||"Failed to load top pages",x(`Error loading top pages: ${i.value}`)}finally{d.value=!1}}e.onMounted(()=>{l.status==="completed"&&b()||w()});function x(t){l.status!=="completed"&&V("submit",t)}const v=t=>{if(!t)return"0s";const s=Math.floor(t/60),n=Math.round(t%60);return s>0?`${s}m ${n}s`:`${n}s`},g=t=>t==null?"0":t.toLocaleString(),S=t=>t?new Date(t).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}):"",P=e.computed(()=>a.value.length===0?1:Math.max(...a.value.map(t=>t.screenPageViews||0))),B=e.computed(()=>{const{startDate:t,endDate:s}=l.resolvedArgs||{};if(!t&&!s)return"Last 30 days";const n=t||"30daysAgo",o=s||"today",r=n.match(/^(\d+)daysAgo$/);return r?`Last ${r[1]} days`:`${n} → ${o}`});return(t,s)=>{const n=e.resolveComponent("NuxtLink");return e.openBlock(),e.createElementBlock("div",T,[e.unref(d)?(e.openBlock(),e.createElementBlock("div",$,[e.createVNode(e.unref(c.Loader2),{class:"size-4 animate-spin text-muted-foreground"}),s[0]||(s[0]=e.createElementVNode("span",{class:"text-xs text-muted-foreground"},"Loading top pages…",-1))])):e.unref(i)?(e.openBlock(),e.createElementBlock("div",L,e.toDisplayString(e.unref(i)),1)):e.unref(a).length===0?(e.openBlock(),e.createElementBlock("div",A,[e.createVNode(e.unref(c.FileText),{class:"size-8 text-muted-foreground mx-auto mb-2"}),s[1]||(s[1]=e.createElementVNode("p",{class:"text-sm text-muted-foreground"},"No page data found for this period.",-1))])):(e.openBlock(),e.createElementBlock("div",M,[e.createElementVNode("div",C,[e.createElementVNode("div",z,[e.createVNode(e.unref(c.FileText),{class:"size-3.5 text-primary"}),s[2]||(s[2]=e.createElementVNode("span",{class:"text-xs font-medium"},"Most Popular Pages",-1))]),e.createElementVNode("span",F,e.toDisplayString(e.unref(B)),1)]),e.createElementVNode("div",I,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(a),(o,r)=>(e.openBlock(),e.createElementBlock("div",{key:r,class:"px-3 py-2.5 hover:bg-muted/30 transition-colors"},[e.createElementVNode("div",j,[e.createElementVNode("span",U,e.toDisplayString(r+1)+".",1),e.createElementVNode("span",{class:"text-xs font-medium truncate flex-1",title:o.pagePath},e.toDisplayString(o.pagePath),9,q)]),e.createElementVNode("div",O,[e.createElementVNode("div",R,[e.createElementVNode("div",{class:"h-full rounded-full bg-primary/70 transition-all",style:e.normalizeStyle({width:`${(o.screenPageViews||0)/e.unref(P)*100}%`})},null,4)]),e.createElementVNode("div",G,[e.createElementVNode("span",H,[e.createVNode(e.unref(c.Eye),{class:"size-2.5"}),e.createTextVNode(" "+e.toDisplayString(g(o.screenPageViews))+" views ",1)]),e.createElementVNode("span",J,[e.createVNode(e.unref(c.Users),{class:"size-2.5"}),e.createTextVNode(" "+e.toDisplayString(g(o.totalUsers))+" users ",1)]),e.createElementVNode("span",K,[e.createVNode(e.unref(c.Clock),{class:"size-2.5"}),e.createTextVNode(" "+e.toDisplayString(v(o.averageSessionDuration)),1)])])])]))),128))]),e.createElementVNode("div",Q,[e.createElementVNode("span",W,[e.createTextVNode(" Top "+e.toDisplayString(e.unref(a).length)+" of "+e.toDisplayString(g(e.unref(u)))+" pages ",1),e.unref(m)?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createTextVNode(" · fetched "+e.toDisplayString(S(e.unref(m))),1)],64)):e.createCommentVNode("",!0)]),e.createVNode(n,{to:`/projects/${e.unref(k)}/modules/${f.instanceId}`,class:"inline-flex items-center gap-1.5 text-xs text-primary hover:underline"},{default:e.withCtx(()=>[e.createVNode(e.unref(c.ExternalLink),{class:"size-3"}),s[3]||(s[3]=e.createTextVNode(" View full report ",-1))]),_:1},8,["to"])])]))])}}});exports.default=X;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import { Loader2 as
|
|
3
|
-
const
|
|
1
|
+
import { defineComponent as F, computed as w, ref as f, onMounted as B, resolveComponent as R, openBlock as d, createElementBlock as u, unref as s, createVNode as c, createElementVNode as a, toDisplayString as i, Fragment as P, renderList as O, normalizeStyle as q, createTextVNode as g, createCommentVNode as G, withCtx as H } from "vue";
|
|
2
|
+
import { Loader2 as J, FileText as S, Eye as K, Users as Q, Clock as W, ExternalLink as X } from "lucide-vue-next";
|
|
3
|
+
const Y = { class: "w-full" }, Z = {
|
|
4
4
|
key: 0,
|
|
5
5
|
class: "flex items-center gap-2 py-3"
|
|
6
|
-
},
|
|
6
|
+
}, ee = {
|
|
7
7
|
key: 1,
|
|
8
8
|
class: "text-xs text-destructive py-2"
|
|
9
|
-
},
|
|
9
|
+
}, te = {
|
|
10
10
|
key: 2,
|
|
11
11
|
class: "rounded-xl border bg-background p-4 text-center"
|
|
12
|
-
},
|
|
12
|
+
}, se = {
|
|
13
13
|
key: 3,
|
|
14
14
|
class: "rounded-xl border bg-background overflow-hidden"
|
|
15
|
-
},
|
|
15
|
+
}, ae = { class: "px-3 py-2 border-b bg-muted/40 flex items-center justify-between" }, oe = { class: "flex items-center gap-2" }, ne = { class: "text-[10px] text-muted-foreground" }, re = { class: "divide-y" }, ie = { class: "flex items-center gap-2 mb-1.5" }, le = { class: "text-[10px] font-medium text-muted-foreground w-5 text-right shrink-0" }, de = ["title"], ue = { class: "ml-7 space-y-1.5" }, ce = { class: "h-1.5 rounded-full bg-muted overflow-hidden" }, me = { class: "flex items-center gap-3 text-[10px] text-muted-foreground" }, ge = { class: "flex items-center gap-1" }, pe = { class: "flex items-center gap-1" }, fe = { class: "flex items-center gap-1" }, xe = { class: "px-3 py-2 border-t bg-muted/20 flex items-center justify-between" }, ve = { class: "text-[10px] text-muted-foreground" }, ye = /* @__PURE__ */ F({
|
|
16
16
|
__name: "TopPagesCard",
|
|
17
17
|
props: {
|
|
18
18
|
toolName: {},
|
|
@@ -23,23 +23,23 @@ const X = { class: "w-full" }, Y = {
|
|
|
23
23
|
status: {}
|
|
24
24
|
},
|
|
25
25
|
emits: ["submit"],
|
|
26
|
-
setup(b, { emit:
|
|
27
|
-
const { $useRoute: L, $
|
|
28
|
-
function
|
|
26
|
+
setup(b, { emit: $ }) {
|
|
27
|
+
const { $useRoute: L, $useModuleApi: A } = useNuxtApp(), m = b, N = $, V = L(), C = w(() => V.params.slug), M = A(m.instanceId), x = f(!0), p = f(null), r = f([]), v = f(0), h = f(null);
|
|
28
|
+
function T() {
|
|
29
29
|
const e = m.resolvedArgs?._cachedData;
|
|
30
30
|
return e ? (r.value = e.pages?.map((t) => ({
|
|
31
31
|
pagePath: t.page,
|
|
32
32
|
screenPageViews: t.views,
|
|
33
33
|
totalUsers: t.users,
|
|
34
|
-
averageSessionDuration:
|
|
34
|
+
averageSessionDuration: z(t.avgDuration)
|
|
35
35
|
})) || [], v.value = e.totalPagesTracked || r.value.length, h.value = m.resolvedArgs._fetchedAt || null, x.value = !1, !0) : !1;
|
|
36
36
|
}
|
|
37
|
-
function
|
|
37
|
+
function z(e) {
|
|
38
38
|
if (!e) return 0;
|
|
39
39
|
const t = e.match(/(\d+)m/), n = e.match(/(\d+)s/);
|
|
40
40
|
return (t ? parseInt(t[1]) * 60 : 0) + (n ? parseInt(n[1]) : 0);
|
|
41
41
|
}
|
|
42
|
-
async function
|
|
42
|
+
async function I() {
|
|
43
43
|
const { startDate: e, endDate: t, limit: n } = m.resolvedArgs || {};
|
|
44
44
|
x.value = !0, p.value = null;
|
|
45
45
|
try {
|
|
@@ -62,88 +62,88 @@ const X = { class: "w-full" }, Y = {
|
|
|
62
62
|
x.value = !1;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
m.status === "completed" &&
|
|
65
|
+
B(() => {
|
|
66
|
+
m.status === "completed" && T() || I();
|
|
67
67
|
});
|
|
68
68
|
function k(e) {
|
|
69
|
-
m.status !== "completed" &&
|
|
69
|
+
m.status !== "completed" && N("submit", e);
|
|
70
70
|
}
|
|
71
71
|
const D = (e) => {
|
|
72
72
|
if (!e) return "0s";
|
|
73
73
|
const t = Math.floor(e / 60), n = Math.round(e % 60);
|
|
74
74
|
return t > 0 ? `${t}m ${n}s` : `${n}s`;
|
|
75
|
-
}, y = (e) => e == null ? "0" : e.toLocaleString(),
|
|
75
|
+
}, y = (e) => e == null ? "0" : e.toLocaleString(), E = (e) => e ? new Date(e).toLocaleString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }) : "", U = w(() => r.value.length === 0 ? 1 : Math.max(...r.value.map((e) => e.screenPageViews || 0))), j = w(() => {
|
|
76
76
|
const { startDate: e, endDate: t } = m.resolvedArgs || {};
|
|
77
77
|
if (!e && !t) return "Last 30 days";
|
|
78
78
|
const n = e || "30daysAgo", o = t || "today", l = n.match(/^(\d+)daysAgo$/);
|
|
79
79
|
return l ? `Last ${l[1]} days` : `${n} → ${o}`;
|
|
80
80
|
});
|
|
81
81
|
return (e, t) => {
|
|
82
|
-
const n =
|
|
83
|
-
return d(), u("div",
|
|
84
|
-
s(x) ? (d(), u("div",
|
|
85
|
-
c(s(
|
|
82
|
+
const n = R("NuxtLink");
|
|
83
|
+
return d(), u("div", Y, [
|
|
84
|
+
s(x) ? (d(), u("div", Z, [
|
|
85
|
+
c(s(J), { class: "size-4 animate-spin text-muted-foreground" }),
|
|
86
86
|
t[0] || (t[0] = a("span", { class: "text-xs text-muted-foreground" }, "Loading top pages…", -1))
|
|
87
|
-
])) : s(p) ? (d(), u("div",
|
|
88
|
-
c(s(
|
|
87
|
+
])) : s(p) ? (d(), u("div", ee, i(s(p)), 1)) : s(r).length === 0 ? (d(), u("div", te, [
|
|
88
|
+
c(s(S), { class: "size-8 text-muted-foreground mx-auto mb-2" }),
|
|
89
89
|
t[1] || (t[1] = a("p", { class: "text-sm text-muted-foreground" }, "No page data found for this period.", -1))
|
|
90
|
-
])) : (d(), u("div",
|
|
91
|
-
a("div",
|
|
92
|
-
a("div",
|
|
93
|
-
c(s(
|
|
90
|
+
])) : (d(), u("div", se, [
|
|
91
|
+
a("div", ae, [
|
|
92
|
+
a("div", oe, [
|
|
93
|
+
c(s(S), { class: "size-3.5 text-primary" }),
|
|
94
94
|
t[2] || (t[2] = a("span", { class: "text-xs font-medium" }, "Most Popular Pages", -1))
|
|
95
95
|
]),
|
|
96
|
-
a("span",
|
|
96
|
+
a("span", ne, i(s(j)), 1)
|
|
97
97
|
]),
|
|
98
|
-
a("div",
|
|
98
|
+
a("div", re, [
|
|
99
99
|
(d(!0), u(P, null, O(s(r), (o, l) => (d(), u("div", {
|
|
100
100
|
key: l,
|
|
101
101
|
class: "px-3 py-2.5 hover:bg-muted/30 transition-colors"
|
|
102
102
|
}, [
|
|
103
|
-
a("div",
|
|
104
|
-
a("span",
|
|
103
|
+
a("div", ie, [
|
|
104
|
+
a("span", le, i(l + 1) + ".", 1),
|
|
105
105
|
a("span", {
|
|
106
106
|
class: "text-xs font-medium truncate flex-1",
|
|
107
107
|
title: o.pagePath
|
|
108
|
-
}, i(o.pagePath), 9,
|
|
108
|
+
}, i(o.pagePath), 9, de)
|
|
109
109
|
]),
|
|
110
|
-
a("div",
|
|
111
|
-
a("div",
|
|
110
|
+
a("div", ue, [
|
|
111
|
+
a("div", ce, [
|
|
112
112
|
a("div", {
|
|
113
113
|
class: "h-full rounded-full bg-primary/70 transition-all",
|
|
114
|
-
style:
|
|
114
|
+
style: q({ width: `${(o.screenPageViews || 0) / s(U) * 100}%` })
|
|
115
115
|
}, null, 4)
|
|
116
116
|
]),
|
|
117
|
-
a("div",
|
|
118
|
-
a("span", me, [
|
|
119
|
-
c(s(J), { class: "size-2.5" }),
|
|
120
|
-
g(" " + i(y(o.screenPageViews)) + " views ", 1)
|
|
121
|
-
]),
|
|
117
|
+
a("div", me, [
|
|
122
118
|
a("span", ge, [
|
|
123
119
|
c(s(K), { class: "size-2.5" }),
|
|
124
|
-
g(" " + i(y(o.
|
|
120
|
+
g(" " + i(y(o.screenPageViews)) + " views ", 1)
|
|
125
121
|
]),
|
|
126
122
|
a("span", pe, [
|
|
127
123
|
c(s(Q), { class: "size-2.5" }),
|
|
124
|
+
g(" " + i(y(o.totalUsers)) + " users ", 1)
|
|
125
|
+
]),
|
|
126
|
+
a("span", fe, [
|
|
127
|
+
c(s(W), { class: "size-2.5" }),
|
|
128
128
|
g(" " + i(D(o.averageSessionDuration)), 1)
|
|
129
129
|
])
|
|
130
130
|
])
|
|
131
131
|
])
|
|
132
132
|
]))), 128))
|
|
133
133
|
]),
|
|
134
|
-
a("div",
|
|
135
|
-
a("span",
|
|
134
|
+
a("div", xe, [
|
|
135
|
+
a("span", ve, [
|
|
136
136
|
g(" Top " + i(s(r).length) + " of " + i(y(s(v))) + " pages ", 1),
|
|
137
137
|
s(h) ? (d(), u(P, { key: 0 }, [
|
|
138
|
-
g(" · fetched " + i(
|
|
139
|
-
], 64)) :
|
|
138
|
+
g(" · fetched " + i(E(s(h))), 1)
|
|
139
|
+
], 64)) : G("", !0)
|
|
140
140
|
]),
|
|
141
141
|
c(n, {
|
|
142
|
-
to: `/projects/${s(
|
|
142
|
+
to: `/projects/${s(C)}/modules/${b.instanceId}`,
|
|
143
143
|
class: "inline-flex items-center gap-1.5 text-xs text-primary hover:underline"
|
|
144
144
|
}, {
|
|
145
|
-
default:
|
|
146
|
-
c(s(
|
|
145
|
+
default: H(() => [
|
|
146
|
+
c(s(X), { class: "size-3" }),
|
|
147
147
|
t[3] || (t[3] = g(" View full report ", -1))
|
|
148
148
|
]),
|
|
149
149
|
_: 1
|