"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={
}
>
{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.",
};