"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { ButtonPrimary, ButtonSecondary } from "components/Buttons"; import { CheckTiny } from "components/Icons/CheckTiny"; import { GoToArrow } from "components/Icons/GoToArrow"; import { Modal } from "components/Modal"; import { useToaster } from "components/Toast"; import { isOAuthSessionError, OAuthErrorMessage } from "components/OAuthError"; import { LinkHandle } from "./HandleSubscribe"; import { EmailInput, EmailConfirm } from "./EmailSubscribe"; import type { ViewerUser } from "./viewerSubscription"; import { requestPublicationEmailSubscription, confirmPublicationEmailSubscription, unsubscribeFromPublication, } from "actions/publications/subscribeEmail"; const BLUESKY_FEED_URL = "https://bsky.app/profile/leaflet.pub/feed/subscribedPublications"; export const ManageSubscription = (props: { publicationUri: string; publicationUrl?: string; newsletterMode: boolean; user: ViewerUser; }) => { const { user } = props; let [email, setEmail] = useState(user.email ?? ""); let [linkEmailOpen, setLinkEmailOpen] = useState(false); let [linkRequesting, setLinkRequesting] = useState(false); let [linkConfirming, setLinkConfirming] = useState(false); let [unsubscribing, setUnsubscribing] = useState(false); let toaster = useToaster(); let router = useRouter(); let prefClassName = "flex gap-2 justify-between font-bold text-secondary items-center"; const onRequestLink = async () => { if (linkRequesting || !email) return; setLinkRequesting(true); const res = await requestPublicationEmailSubscription( props.publicationUri, email, ); setLinkRequesting(false); if (!res.ok) { toaster({ type: "error", content: (
{LINK_ERROR_MESSAGES[res.error] ?? "Couldn't link email."}
), }); return; } if (res.value.confirmed) { toaster({ content:
Email Linked!
, type: "success", }); setLinkEmailOpen(false); router.refresh(); return; } setLinkEmailOpen(true); }; const onConfirmLink = async (code: string) => { if (linkConfirming) return; setLinkConfirming(true); const res = await confirmPublicationEmailSubscription( props.publicationUri, email, code, ); setLinkConfirming(false); if (!res.ok) { toaster({ type: "error", content: (
{LINK_ERROR_MESSAGES[res.error] ?? "Couldn't confirm code."}
), }); return; } toaster({ content:
Email Linked!
, type: "success", }); setLinkEmailOpen(false); router.refresh(); }; const onUnsubscribe = async () => { if (unsubscribing) return; setUnsubscribing(true); const res = await unsubscribeFromPublication(props.publicationUri); setUnsubscribing(false); if (!res.ok) { toaster({ type: "error", content: isOAuthSessionError(res.error) ? ( ) : (
{UNSUBSCRIBE_ERROR_MESSAGES[res.error] ?? "Couldn't unsubscribe."}
), }); return; } toaster({ content:
Unsubscribed.
, type: "success", }); router.refresh(); }; return ( Manage Subscription } className="w-md max-w-full" trigger={
Subscribed
Manage
} >
{props.newsletterMode && user.email ? (

Linked Email

{user.email}

) : null} {user.handle && (
Linked Handle

{user.handle}

)} {props.publicationUrl && ( RSS Feed )} Bluesky Feed {props.newsletterMode && !user.email ? (

Link your email

to get updates right to your inbox!
link } > setLinkEmailOpen(false)} onSubmit={onConfirmLink} /> } />
) : null} {!user.handle ? (
) : null}
{unsubscribing ? "Unsubscribing…" : "Unsubscribe"}
); }; const LINK_ERROR_MESSAGES: Record = { invalid_email: "Please enter a valid email address.", newsletter_disabled: "This publication isn't accepting email subscriptions.", email_send_failed: "We couldn't send the confirmation email. Try again.", subscriber_not_found: "No pending subscription. Start over.", invalid_code: "That code didn't match. Try again.", database_error: "Something went wrong. Try again.", suppressed_spam_complaint: "This address was previously marked as spam and can't be linked. Contact the publication to resolve.", suppression_delete_failed: "We couldn't clear a prior delivery issue on this address. Try again later.", }; const UNSUBSCRIBE_ERROR_MESSAGES: Record = { unauthorized: "Sign in to manage your subscription.", not_subscribed: "We couldn't find an email subscription for this publication.", database_error: "Something went wrong. Try again.", };