import Link from "next/link"; import { redirect } from "next/navigation"; import { ArrowLeftIcon, PencilIcon, CalendarIcon, UsersIcon, FileTextIcon, SmartphoneIcon, RepeatIcon, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; import { getSeededOperator } from "@/lib/operator"; import { getAccount, listGroupsForAccount } from "@/lib/queries"; import { ReviewSubmitClient } from "./review-submit-client"; import { DateTime } from "luxon"; import { describeRecurrence, kindFromRrule } from "@/lib/recurrence"; interface StepReviewParams { step?: string; accountId?: string; groupIds?: string; text?: string; mediaId?: string; caption?: string; scheduledAt?: string; rrule?: string; } interface StepReviewProps { params: StepReviewParams; } const WEEKDAY_TO_ISO: Record = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7, }; function parseWeeklyDaysFromRrule(rrule: string | undefined): number[] { if (!rrule) return []; const m = rrule.match(/BYDAY=([A-Z,]+)/i); if (!m) return []; return m[1]! .split(",") .map((d) => WEEKDAY_TO_ISO[d.toUpperCase()]) .filter((d): d is number => d !== undefined); } function formatScheduledAt(iso: string, timezone: string): string { try { const dt = DateTime.fromISO(iso, { zone: timezone }); if (!dt.isValid) return iso; return dt.toLocaleString(DateTime.DATETIME_FULL); } catch { return iso; } } function editLink( step: number, accountId: string, groupIds?: string, text?: string, mediaId?: string, caption?: string, scheduledAt?: string, rrule?: string, ): string { const sp = new URLSearchParams({ step: String(step), accountId }); if (groupIds) sp.set("groupIds", groupIds); if (text) sp.set("text", text); if (mediaId) sp.set("mediaId", mediaId); if (caption) sp.set("caption", caption); if (scheduledAt) sp.set("scheduledAt", scheduledAt); if (rrule) sp.set("rrule", rrule); return `/reminders/new?${sp.toString()}`; } export async function StepReview({ params }: StepReviewProps) { const { accountId, groupIds, text, mediaId, caption, scheduledAt, rrule } = params; if (!accountId || !scheduledAt || (!text && !mediaId)) { // eslint-disable-next-line @typescript-eslint/no-explicit-any redirect("/reminders/new" as any); } const op = await getSeededOperator(); const timezone = op.defaultTimezone ?? "UTC"; // Fetch account details const account = await getAccount(op.id, accountId); if (!account) { // eslint-disable-next-line @typescript-eslint/no-explicit-any redirect("/reminders/new" as any); } // Fetch group names const groupIdsArray = groupIds ? groupIds.split(",").filter(Boolean) : []; const groupsResult = groupIdsArray.length > 0 ? await listGroupsForAccount(op.id, accountId) : null; const selectedGroups = groupsResult ? groupsResult.groups.filter((g) => groupIdsArray.includes(g.id)) : []; const formattedDate = formatScheduledAt(scheduledAt, timezone); // Back goes to step 4 (Groups, the previous step in the new order) const backHref = editLink(4, accountId, groupIds, text, mediaId, caption, scheduledAt, rrule); return (

Review your reminder before scheduling.

{/* Account */} } label="Account" editHref={editLink(1, accountId, groupIds, text, mediaId, caption, scheduledAt, rrule)} > {account.label} {account.phoneNumber && ( {account.phoneNumber} )} {/* Message */} } label="Message" editHref={editLink(2, accountId, groupIds, text, mediaId, caption, scheduledAt, rrule)} > {mediaId ? ( Media file {caption && ( <> with caption: {caption} )} {text && ( <> · {text} )} ) : text ? (

{text}

) : ( No message )}
{/* When */} } label={rrule ? "First fire" : "When"} editHref={editLink(3, accountId, groupIds, text, mediaId, caption, scheduledAt, rrule)} > {formattedDate} {/* Recurrence (only if set) */} {rrule && ( } label="Repeats" editHref={editLink(3, accountId, groupIds, text, mediaId, caption, scheduledAt, rrule)} > {describeRecurrence( kindFromRrule(rrule), DateTime.fromISO(scheduledAt!, { zone: timezone }), parseWeeklyDaysFromRrule(rrule), )} )} {/* Groups */} } label="Groups" editHref={editLink(4, accountId, groupIds, text, mediaId, caption, scheduledAt, rrule)} > {selectedGroups.length > 0 ? (
{selectedGroups.map((g) => ( {g.name} ))}
) : ( No groups — reminder will be saved without targets )}
); } function ReviewRow({ icon, label, editHref, children, }: { icon: React.ReactNode; label: string; editHref: string; children: React.ReactNode; }) { return (
{icon}

{label}

{children}
Edit
); }