Skip to content

Commit 1e75e34

Browse files
committed
stats links
1 parent 0a7892a commit 1e75e34

3 files changed

Lines changed: 65 additions & 28 deletions

File tree

TODO.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
# TODO
22

33
- test webhooks for email providers
4-
- test winning variations
54
- test the docker compose
65
- docs: installation, email providers, templates, contacts, lists, workspaces, broadcast campaigns, transactional api, notification center
7-
- test 2 subscribers only AB test
86

97
## Eventual features
108

console/src/components/broadcasts/BroadcastStats.tsx

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ import {
1010
} from '@fortawesome/free-regular-svg-icons'
1111
import { faArrowPointer, faTriangleExclamation, faBan } from '@fortawesome/free-solid-svg-icons'
1212
import { getBroadcastStats } from '../../services/api/messages_history'
13+
import { useNavigate } from '@tanstack/react-router'
1314

1415
interface BroadcastStatsProps {
1516
workspaceId: string
1617
broadcastId: string
1718
}
1819

1920
export function BroadcastStats({ workspaceId, broadcastId }: BroadcastStatsProps) {
21+
const navigate = useNavigate()
22+
2023
const { data, isLoading } = useQuery({
2124
queryKey: ['broadcast-stats', workspaceId, broadcastId],
2225
queryFn: async () => {
@@ -39,7 +42,24 @@ export function BroadcastStats({ workspaceId, broadcastId }: BroadcastStatsProps
3942

4043
const getRate = (numerator: number, denominator: number) => {
4144
if (denominator === 0) return '-'
42-
return `${((numerator / denominator) * 100).toFixed(1)}%`
45+
const percentage = (numerator / denominator) * 100
46+
if (percentage === 0 || percentage >= 10) {
47+
return `${Math.round(percentage)}%`
48+
}
49+
return `${percentage.toFixed(1)}%`
50+
}
51+
52+
// Function to navigate to logs page with specific filter
53+
const navigateToLogs = (filterType: string) => {
54+
const searchParams = new URLSearchParams()
55+
searchParams.set('broadcast_id', broadcastId)
56+
57+
if (filterType !== 'sent') {
58+
searchParams.set(filterType, 'true')
59+
}
60+
61+
const url = `/workspace/${workspaceId}/logs?${searchParams.toString()}`
62+
navigate({ to: url as any })
4363
}
4464

4565
// Formatter function for statistics that handles loading state
@@ -53,8 +73,11 @@ export function BroadcastStats({ workspaceId, broadcastId }: BroadcastStatsProps
5373
return (
5474
<Row gutter={[16, 16]} wrap className="flex-nowrap overflow-x-auto">
5575
<Col span={3}>
56-
<Tooltip title={`${stats.total_sent} total emails sent`}>
57-
<div>
76+
<Tooltip title={`${stats.total_sent} total emails sent - Click to view details`}>
77+
<div
78+
className="cursor-pointer hover:bg-gray-50 p-2 rounded transition-colors"
79+
onClick={() => navigateToLogs('sent')}
80+
>
5881
<Statistic
5982
title={
6083
<Space className="font-medium">
@@ -74,8 +97,13 @@ export function BroadcastStats({ workspaceId, broadcastId }: BroadcastStatsProps
7497
</Tooltip>
7598
</Col>
7699
<Col span={3}>
77-
<Tooltip title={`${stats.total_delivered} emails successfully delivered`}>
78-
<div>
100+
<Tooltip
101+
title={`${stats.total_delivered} emails successfully delivered - Click to view details`}
102+
>
103+
<div
104+
className="cursor-pointer hover:bg-gray-50 p-2 rounded transition-colors"
105+
onClick={() => navigateToLogs('is_delivered')}
106+
>
79107
<Statistic
80108
title={
81109
<Space className="font-medium">
@@ -95,8 +123,11 @@ export function BroadcastStats({ workspaceId, broadcastId }: BroadcastStatsProps
95123
</Tooltip>
96124
</Col>
97125
<Col span={3}>
98-
<Tooltip title={`${stats.total_opened} total opens`}>
99-
<div>
126+
<Tooltip title={`${stats.total_opened} total opens - Click to view details`}>
127+
<div
128+
className="cursor-pointer hover:bg-gray-50 p-2 rounded transition-colors"
129+
onClick={() => navigateToLogs('is_opened')}
130+
>
100131
<Statistic
101132
title={
102133
<Space className="font-medium">
@@ -116,8 +147,11 @@ export function BroadcastStats({ workspaceId, broadcastId }: BroadcastStatsProps
116147
</Tooltip>
117148
</Col>
118149
<Col span={3}>
119-
<Tooltip title={`${stats.total_clicked} total clicks`}>
120-
<div>
150+
<Tooltip title={`${stats.total_clicked} total clicks - Click to view details`}>
151+
<div
152+
className="cursor-pointer hover:bg-gray-50 p-2 rounded transition-colors"
153+
onClick={() => navigateToLogs('is_clicked')}
154+
>
121155
<Statistic
122156
title={
123157
<Space className="font-medium">
@@ -137,8 +171,11 @@ export function BroadcastStats({ workspaceId, broadcastId }: BroadcastStatsProps
137171
</Tooltip>
138172
</Col>
139173
<Col span={3}>
140-
<Tooltip title={`${stats.total_failed} emails failed to send`}>
141-
<div>
174+
<Tooltip title={`${stats.total_failed} emails failed to send - Click to view details`}>
175+
<div
176+
className="cursor-pointer hover:bg-gray-50 p-2 rounded transition-colors"
177+
onClick={() => navigateToLogs('is_failed')}
178+
>
142179
<Statistic
143180
title={
144181
<Space className="font-medium">
@@ -158,8 +195,11 @@ export function BroadcastStats({ workspaceId, broadcastId }: BroadcastStatsProps
158195
</Tooltip>
159196
</Col>
160197
<Col span={3}>
161-
<Tooltip title={`${stats.total_bounced} emails bounced back`}>
162-
<div>
198+
<Tooltip title={`${stats.total_bounced} emails bounced back - Click to view details`}>
199+
<div
200+
className="cursor-pointer hover:bg-gray-50 p-2 rounded transition-colors"
201+
onClick={() => navigateToLogs('is_bounced')}
202+
>
163203
<Statistic
164204
title={
165205
<Space className="font-medium">
@@ -179,8 +219,11 @@ export function BroadcastStats({ workspaceId, broadcastId }: BroadcastStatsProps
179219
</Tooltip>
180220
</Col>
181221
<Col span={3}>
182-
<Tooltip title={`${stats.total_complained} total complaints`}>
183-
<div>
222+
<Tooltip title={`${stats.total_complained} total complaints - Click to view details`}>
223+
<div
224+
className="cursor-pointer hover:bg-gray-50 p-2 rounded transition-colors"
225+
onClick={() => navigateToLogs('is_complained')}
226+
>
184227
<Statistic
185228
title={
186229
<Space className="font-medium">
@@ -200,8 +243,11 @@ export function BroadcastStats({ workspaceId, broadcastId }: BroadcastStatsProps
200243
</Tooltip>
201244
</Col>
202245
<Col span={3}>
203-
<Tooltip title={`${stats.total_unsubscribed} total unsubscribes`}>
204-
<div>
246+
<Tooltip title={`${stats.total_unsubscribed} total unsubscribes - Click to view details`}>
247+
<div
248+
className="cursor-pointer hover:bg-gray-50 p-2 rounded transition-colors"
249+
onClick={() => navigateToLogs('is_unsubscribed')}
250+
>
205251
<Statistic
206252
title={
207253
<Space className="font-medium">

internal/domain/message_history.go

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -322,15 +322,8 @@ func (p *MessageListParams) Validate() error {
322322
return fmt.Errorf("invalid contact email format")
323323
}
324324

325-
// Validate broadcast ID if provided
326-
if p.BroadcastID != "" && !govalidator.IsUUID(p.BroadcastID) {
327-
return fmt.Errorf("invalid broadcast ID format")
328-
}
329-
330-
// Validate template ID if provided
331-
if p.TemplateID != "" && !govalidator.IsUUID(p.TemplateID) {
332-
return fmt.Errorf("invalid template ID format")
333-
}
325+
// Note: BroadcastID and TemplateID are not validated as UUIDs
326+
// They can be any non-empty string format
334327

335328
// Validate time ranges
336329
if p.SentAfter != nil && p.SentBefore != nil {

0 commit comments

Comments
 (0)