diff --git a/apps/web/package.json b/apps/web/package.json
index 8d31720..7a996bc 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -37,6 +37,7 @@
"@uiw/react-codemirror": "^4.25.3",
"@xyflow/react": "^12.9.3",
"dagre": "^0.8.5",
+ "dayjs": "^1.11.19",
"framer-motion": "^12.23.24",
"juice": "^11.0.3",
"lucide-react": "^0.553.0",
diff --git a/apps/web/src/components/BillingLimits.tsx b/apps/web/src/components/BillingLimits.tsx
index eb1ce43..5d757e2 100644
--- a/apps/web/src/components/BillingLimits.tsx
+++ b/apps/web/src/components/BillingLimits.tsx
@@ -1,4 +1,4 @@
-import {memo, useCallback, useEffect, useMemo, useState} from 'react';
+import {memo, useEffect, useMemo, useState} from 'react';
import {useForm} from 'react-hook-form';
import {zodResolver} from '@hookform/resolvers/zod';
import {BillingLimitSchemas} from '@plunk/shared';
@@ -23,7 +23,7 @@ import {
import {AlertCircle, AlertTriangle, Check} from 'lucide-react';
import {AnimatePresence, motion} from 'framer-motion';
import type {z} from 'zod';
-import {useBillingLimits, type BillingLimitsData, type CategoryLimit} from '../lib/hooks/useBillingLimits';
+import {type BillingLimitsData, type CategoryLimit, useBillingLimits} from '../lib/hooks/useBillingLimits';
import {network} from '../lib/network';
// Price per email in the smallest currency unit (e.g., cents for USD/EUR)
@@ -50,7 +50,7 @@ const formatEmailCost = (emailCount: number, currency: string | null): string =>
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(costInCents / 100);
- } catch (error) {
+ } catch {
// Fallback if currency is invalid
return `${(costInCents / 100).toFixed(2)} ${currency.toUpperCase()}`;
}
@@ -167,8 +167,8 @@ export function BillingLimits({projectId, hasSubscription, billingEnabled}: Bill
- You're on the free tier with 1,000 emails per month. Upgrade to a paid subscription for
- unlimited emails or custom limits.
+ You're on the free tier with 1,000 emails per month. Upgrade to a paid subscription for unlimited
+ emails or custom limits.
@@ -254,9 +254,7 @@ export function BillingLimits({projectId, hasSubscription, billingEnabled}: Bill
Maximum workflow emails per month. Leave empty for unlimited.
- {estimatedCost && (
- ≈ {estimatedCost}/month
- )}
+ {estimatedCost && ≈ {estimatedCost}/month}
@@ -286,9 +284,7 @@ export function BillingLimits({projectId, hasSubscription, billingEnabled}: Bill
Maximum campaign emails per month. Leave empty for unlimited.
- {estimatedCost && (
- ≈ {estimatedCost}/month
- )}
+ {estimatedCost && ≈ {estimatedCost}/month}
@@ -318,9 +314,7 @@ export function BillingLimits({projectId, hasSubscription, billingEnabled}: Bill
Maximum transactional emails per month. Leave empty for unlimited.
- {estimatedCost && (
- ≈ {estimatedCost}/month
- )}
+ {estimatedCost && ≈ {estimatedCost}/month}
diff --git a/apps/web/src/components/TemplateSelectionDialog.tsx b/apps/web/src/components/TemplateSelectionDialog.tsx
index cc2b08e..b9a5f96 100644
--- a/apps/web/src/components/TemplateSelectionDialog.tsx
+++ b/apps/web/src/components/TemplateSelectionDialog.tsx
@@ -13,10 +13,9 @@ import {
DialogHeader,
DialogTitle,
Input,
- Label,
+ Label
} from '@plunk/ui';
import type {Template} from '@plunk/db';
-import {network} from '../lib/network';
import {ArrowLeft, FileText, Search} from 'lucide-react';
import {useState} from 'react';
import useSWR from 'swr';
@@ -127,168 +126,168 @@ export function TemplateSelectionDialog({open, onOpenChange, onSelectTemplate}:
{step === 'select' ? (
- {/* Search & Filters */}
-
-
@@ -406,7 +408,9 @@ export default function CampaignDetailsPage() {
Send Now
- Send immediately to all recipients
+
+ Send immediately to all recipients
+
@@ -576,7 +580,8 @@ export default function CampaignDetailsPage() {
- This count will be recalculated right before sending to ensure accuracy. The final number may differ if contacts subscribe, unsubscribe, or segment membership changes.
+ This count will be recalculated right before sending to ensure accuracy. The final number may
+ differ if contacts subscribe, unsubscribe, or segment membership changes.
diff --git a/apps/web/src/pages/segments/index.tsx b/apps/web/src/pages/segments/index.tsx
index 52c7bd2..b34cf90 100644
--- a/apps/web/src/pages/segments/index.tsx
+++ b/apps/web/src/pages/segments/index.tsx
@@ -13,12 +13,13 @@ import type {Segment} from '@plunk/db';
import type {FilterCondition} from '@plunk/types';
import {DashboardLayout} from '../../components/DashboardLayout';
import {network} from '../../lib/network';
-import {AlertTriangle, Edit, Filter, Plus, Trash2, Users} from 'lucide-react';
+import {AlertTriangle, Calendar, Edit, Filter, Plus, Trash2, Users} from 'lucide-react';
import {NextSeo} from 'next-seo';
import Link from 'next/link';
import {useState} from 'react';
import {toast} from 'sonner';
import useSWR from 'swr';
+import dayjs from 'dayjs';
// Helper function to count total filters in a condition
function countFiltersInCondition(condition: unknown): number {
@@ -194,8 +195,22 @@ export default function SegmentsPage() {
{/* Metadata */}
-
- Created {new Date(segment.createdAt).toLocaleDateString()}
+