feat: Improved createdAt and updatedAt visualisation

This commit is contained in:
Dries Augustyns
2025-12-11 10:57:56 +01:00
parent 6b25bbe2f8
commit 1019ba0d82
15 changed files with 320 additions and 245 deletions
+9 -12
View File
@@ -397,7 +397,9 @@ export default function CampaignDetailsPage() {
<TestTube className="h-4 w-4 mt-0.5 text-neutral-700" />
<div className="flex flex-col gap-0.5 flex-1">
<span className="font-medium text-sm">Send Test Email</span>
<span className="text-xs text-neutral-500 leading-snug">Preview in your inbox before sending</span>
<span className="text-xs text-neutral-500 leading-snug">
Preview in your inbox before sending
</span>
</div>
</div>
</DropdownMenuItem>
@@ -406,7 +408,9 @@ export default function CampaignDetailsPage() {
<Send className="h-4 w-4 mt-0.5 text-neutral-700" />
<div className="flex flex-col gap-0.5 flex-1">
<span className="font-medium text-sm">Send Now</span>
<span className="text-xs text-neutral-500 leading-snug">Send immediately to all recipients</span>
<span className="text-xs text-neutral-500 leading-snug">
Send immediately to all recipients
</span>
</div>
</div>
</DropdownMenuItem>
@@ -576,7 +580,8 @@ export default function CampaignDetailsPage() {
<div className="flex items-start gap-2">
<Info className="h-3.5 w-3.5 text-blue-600 mt-0.5 flex-shrink-0" />
<p className="text-xs text-blue-800">
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.
</p>
</div>
</div>
@@ -1004,9 +1009,7 @@ export default function CampaignDetailsPage() {
{c.status === CampaignStatus.SCHEDULED && (
<div className="flex items-start gap-1.5 p-2 bg-blue-50 border border-blue-200 rounded">
<Info className="h-3 w-3 text-blue-600 mt-0.5 flex-shrink-0" />
<p className="text-xs text-blue-800">
Recipient count will be recalculated at send time
</p>
<p className="text-xs text-blue-800">Recipient count will be recalculated at send time</p>
</div>
)}
</div>
@@ -1026,12 +1029,6 @@ export default function CampaignDetailsPage() {
</div>
</div>
)}
{/* Created */}
<div>
<p className="text-xs font-medium text-neutral-500 uppercase tracking-wide mb-2">Created</p>
<p className="text-sm text-neutral-900">{new Date(c.createdAt).toLocaleDateString()}</p>
</div>
</CardContent>
</Card>
</div>
+2 -2
View File
@@ -78,7 +78,7 @@ export default function CreateCampaignPage() {
setBody(template.data.body);
toast.success('Template loaded successfully');
} catch (error) {
} catch {
toast.error('Failed to load template');
} finally {
setLoadingTemplate(false);
@@ -104,7 +104,7 @@ export default function CreateCampaignPage() {
setBody(campaign.data.body);
toast.success('Campaign loaded successfully');
} catch (error) {
} catch {
toast.error('Failed to load campaign');
} finally {
setLoadingTemplate(false);
+20
View File
@@ -30,6 +30,7 @@ import {useRouter} from 'next/router';
import {useState} from 'react';
import {toast} from 'sonner';
import useSWR from 'swr';
import dayjs from 'dayjs';
interface PaginatedCampaigns {
campaigns: Campaign[];
@@ -465,6 +466,25 @@ export default function CampaignsPage() {
)}
</div>
{/* Metadata */}
<div className="flex items-center gap-4 text-xs text-neutral-500 pt-3 border-t border-neutral-100">
<div className="flex items-center gap-1.5">
<Calendar className="h-3 w-3" />
<div className="group relative inline-block cursor-help">
<span>Created {dayjs(campaign.createdAt).fromNow()}</span>
<div className="hidden group-hover:block absolute z-10 w-48 p-2 bg-neutral-900 text-white text-xs rounded shadow-lg bottom-full left-0 mb-1 whitespace-nowrap">
{dayjs(campaign.createdAt).format('DD MMMM YYYY, hh:mm')}
</div>
</div>
</div>
<div className="group relative inline-block cursor-help">
<span> Updated {dayjs(campaign.updatedAt).fromNow()}</span>
<div className="hidden group-hover:block absolute z-10 w-48 p-2 bg-neutral-900 text-white text-xs rounded shadow-lg bottom-full left-0 mb-1 whitespace-nowrap">
{dayjs(campaign.updatedAt).format('DD MMMM YYYY, hh:mm')}
</div>
</div>
</div>
{/* Actions */}
<div className="flex gap-2 pt-2 border-t border-neutral-100">
<Link href={`/campaigns/${campaign.id}`} className="flex-1">