+
{result.errors.slice(0, 10).map((error, idx) => (
-
{error.error}
+
+ {error.error}
+
))}
{result.errors.length > 10 && (
-
- ...and {result.errors.length - 10} more errors
+
+ +{result.errors.length - 10} more errors
)}
@@ -1177,12 +1133,9 @@ function BulkActionsDialog({open, onOpenChange, operation, contactIds, onSuccess
)}
{status === 'failed' && (
-
-
-
- Operation failed
-
-
{errorMessage || 'Please try again.'}
+
+
+
{errorMessage || 'Please try again.'}
)}
diff --git a/apps/web/src/pages/index.tsx b/apps/web/src/pages/index.tsx
index 4439884..06faecc 100644
--- a/apps/web/src/pages/index.tsx
+++ b/apps/web/src/pages/index.tsx
@@ -38,22 +38,22 @@ export default function Index() {
const stats = [
{
name: 'Total Contacts',
- value: isLoading ? '-' : totalContacts.toLocaleString(),
+ value: totalContacts.toLocaleString(),
icon: Users,
},
{
name: 'Emails Sent',
- value: isLoading ? '-' : totalEmailsSent.toLocaleString(),
+ value: totalEmailsSent.toLocaleString(),
icon: Mail,
},
{
name: 'Campaigns',
- value: isLoading ? '-' : totalCampaigns.toLocaleString(),
+ value: totalCampaigns.toLocaleString(),
icon: Send,
},
{
name: 'Open Rate',
- value: isLoading ? '-' : `${openRate.toFixed(1)}%`,
+ value: `${openRate.toFixed(1)}%`,
icon: TrendingUp,
},
];
@@ -173,9 +173,6 @@ export default function Index() {
{/* Header */}
Dashboard
-
- Welcome back to {activeProject?.name || 'Plunk'}. Here's what's happening with your emails.
-
{/* Stats Grid */}
@@ -189,7 +186,13 @@ export default function Index() {
{stat.name}
-
{stat.value}
+
+ {isLoading ? (
+
+ ) : (
+ stat.value
+ )}
+
);
diff --git a/apps/web/src/pages/segments/[id].tsx b/apps/web/src/pages/segments/[id].tsx
index b6a5417..db00d3c 100644
--- a/apps/web/src/pages/segments/[id].tsx
+++ b/apps/web/src/pages/segments/[id].tsx
@@ -13,7 +13,7 @@ import type {Contact, Segment} from '@plunk/db';
import type {PaginatedResponse} from '@plunk/types';
import {DashboardLayout} from '../../components/DashboardLayout';
import {network} from '../../lib/network';
-import {ArrowLeft, Database, Filter, MailCheck, MailX, RefreshCw, Save, Trash2, UserMinus, Users} from 'lucide-react';
+import {ArrowLeft, Database, Filter, Layers, MailCheck, MailX, RefreshCw, Save, Trash2, UserMinus, Users} from 'lucide-react';
import Link from 'next/link';
import {useRouter} from 'next/router';
import {useEffect, useState} from 'react';
@@ -310,7 +310,11 @@ export default function SegmentDetailPage() {
{/* Filter Builder (DYNAMIC only) */}
{!isStatic && (
-
+
+ Filter Conditions
+ Build complex audience filters with AND/OR logic
+
+
@@ -346,7 +350,9 @@ export default function SegmentDetailPage() {
>
{isAddingMembers
? 'Adding...'
- : `Add ${pickedEmails.length > 0 ? pickedEmails.length : ''} Contact${pickedEmails.length !== 1 ? 's' : ''}`}
+ : pickedEmails.length > 0
+ ? `Add ${pickedEmails.length} Contact${pickedEmails.length !== 1 ? 's' : ''}`
+ : 'Add Contacts'}
@@ -477,7 +483,7 @@ export default function SegmentDetailPage() {
) : (
@@ -175,17 +176,17 @@ export default function SegmentsPage() {