Skip to content

Commit 18a0d77

Browse files
committed
cooking
1 parent 038234d commit 18a0d77

File tree

3 files changed

+80
-3
lines changed

3 files changed

+80
-3
lines changed

apps/dashboard/app/(main)/websites/[id]/users/[userId]/page.tsx

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { ArrowLeftIcon, SpinnerIcon, UserIcon } from '@phosphor-icons/react';
44
import dayjs from 'dayjs';
55
import { useParams, useRouter } from 'next/navigation';
6+
import { FaviconImage } from '@/components/analytics/favicon-image';
67
import { BrowserIcon, CountryFlag, OSIcon } from '@/components/icon';
78
import { Badge } from '@/components/ui/badge';
89
import { Button } from '@/components/ui/button';
@@ -21,6 +22,45 @@ export default function UserDetailPage() {
2122
dateRange
2223
);
2324

25+
function getReferrerInfo(referrer?: string) {
26+
if (!referrer || referrer === 'direct') {
27+
return { name: 'Direct', domain: null } as {
28+
name: string;
29+
domain: string | null;
30+
};
31+
}
32+
try {
33+
const url = new URL(
34+
referrer.startsWith('http') ? referrer : `https://${referrer}`
35+
);
36+
const domain = url.hostname.replace('www.', '');
37+
return { name: domain, domain } as {
38+
name: string;
39+
domain: string | null;
40+
};
41+
} catch {
42+
return { name: referrer, domain: null } as {
43+
name: string;
44+
domain: string | null;
45+
};
46+
}
47+
}
48+
49+
const totalEvents =
50+
userProfile?.sessions?.reduce(
51+
(acc: number, s: any) =>
52+
acc + (Array.isArray(s.events) ? s.events.length : 0),
53+
0
54+
) || 0;
55+
const totalPages =
56+
userProfile?.sessions?.reduce(
57+
(acc: number, s: any) => acc + (Number(s.page_views) || 0),
58+
0
59+
) || 0;
60+
const avgPagesPerSession = userProfile?.total_sessions
61+
? totalPages / userProfile.total_sessions
62+
: 0;
63+
2464
const handleBack = () => {
2565
router.push(`/websites/${websiteId}/users`);
2666
};
@@ -187,7 +227,7 @@ export default function UserDetailPage() {
187227
<div className="flex min-h-0 flex-1 flex-col overflow-hidden">
188228
<div className="grid grid-cols-1 gap-0 lg:grid-cols-3">
189229
{/* User Overview */}
190-
<div className="border-b bg-background lg:border-r lg:border-b-0">
230+
<div className="border-b bg-background lg:sticky lg:top-[89px] lg:h-[calc(100vh-89px)] lg:overflow-auto lg:border-r lg:border-b-0">
191231
<div className="px-4 py-6">
192232
<h2 className="mb-4 font-semibold text-foreground text-lg">
193233
User Overview
@@ -244,6 +284,20 @@ export default function UserDetailPage() {
244284
Pageviews
245285
</div>
246286
</div>
287+
<div className="rounded-lg border bg-muted/20 p-4 text-center">
288+
<div className="font-bold text-2xl text-foreground">
289+
{totalEvents}
290+
</div>
291+
<div className="text-muted-foreground text-sm">Events</div>
292+
</div>
293+
<div className="rounded-lg border bg-muted/20 p-4 text-center">
294+
<div className="font-bold text-2xl text-foreground">
295+
{avgPagesPerSession.toFixed(1)}
296+
</div>
297+
<div className="text-muted-foreground text-sm">
298+
Pages / Session
299+
</div>
300+
</div>
247301
</div>
248302

249303
{/* Visit Info */}
@@ -347,6 +401,28 @@ export default function UserDetailPage() {
347401
</div>
348402
</div>
349403

404+
{/* Referrer chip */}
405+
{(session.referrer || session.referrer_parsed) && (
406+
<div className="mb-3 inline-flex items-center gap-2 rounded border bg-background px-2 py-1 text-xs">
407+
{(() => {
408+
const info = getReferrerInfo(session.referrer);
409+
return info.domain ? (
410+
<FaviconImage
411+
className="flex-shrink-0"
412+
domain={info.domain}
413+
size={14}
414+
/>
415+
) : null;
416+
})()}
417+
<span className="text-muted-foreground">
418+
Referrer:
419+
</span>
420+
<span className="font-medium">
421+
{getReferrerInfo(session.referrer).name}
422+
</span>
423+
</div>
424+
)}
425+
350426
{/* Event Timeline */}
351427
{session.events && session.events.length > 0 && (
352428
<div>

apps/dashboard/app/(main)/websites/[id]/users/_components/user-row.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import { getCountryName } from '@databuddy/shared';
34
import { ArrowSquareOutIcon } from '@phosphor-icons/react';
45
import dayjs from 'dayjs';
56
import { useRouter } from 'next/navigation';
@@ -93,7 +94,7 @@ export function UserRow({ user, index, websiteId }: UserRowProps) {
9394
<CountryFlag country={user.country} size="sm" />
9495
<div className="min-w-0">
9596
<div className="truncate font-medium text-foreground text-sm">
96-
{user.country || 'Unknown'}
97+
{getCountryName(user.country) || 'Unknown'}
9798
</div>
9899
{user.region && user.region !== 'Unknown' && (
99100
<div className="truncate text-muted-foreground text-xs">

apps/dashboard/next.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ const nextConfig: NextConfig = {
2121
'localhost',
2222
'icons.duckduckgo.com',
2323
'flagcdn.com',
24+
'multiavatar.com',
2425
],
2526
},
2627

2728
output: 'standalone',
28-
transpilePackages: ['@t3-oss/env-nextjs', '@t3-oss/env-core'],
2929
};
3030

3131
export function headers() {

0 commit comments

Comments
 (0)