2023-04-13 18:43:43 +00:00
|
|
|
import { useEffect, useState } from "react";
|
2023-04-17 20:33:55 +00:00
|
|
|
import { FormattedDate, FormattedMessage, FormattedNumber, useIntl } from "react-intl";
|
2023-04-13 18:43:43 +00:00
|
|
|
import { Link } from "react-router-dom";
|
|
|
|
|
|
|
|
import PageSpinner from "Element/PageSpinner";
|
|
|
|
import useEventPublisher from "Feed/EventPublisher";
|
2023-04-17 20:33:55 +00:00
|
|
|
import SnortApi, { Subscription, SubscriptionError } from "SnortApi";
|
|
|
|
import { mapPlanName, mapSubscriptionErrorCode } from ".";
|
2023-04-13 18:43:43 +00:00
|
|
|
import Icon from "Icons/Icon";
|
2023-04-17 20:33:55 +00:00
|
|
|
import AsyncButton from "Element/AsyncButton";
|
|
|
|
import SendSats from "Element/SendSats";
|
2023-04-13 18:43:43 +00:00
|
|
|
|
|
|
|
export default function ManageSubscriptionPage() {
|
|
|
|
const publisher = useEventPublisher();
|
2023-04-17 20:33:55 +00:00
|
|
|
const { formatMessage } = useIntl();
|
2023-04-13 18:43:43 +00:00
|
|
|
const api = new SnortApi(undefined, publisher);
|
|
|
|
|
|
|
|
const [subs, setSubs] = useState<Array<Subscription>>();
|
2023-04-17 20:33:55 +00:00
|
|
|
const [error, setError] = useState<SubscriptionError>();
|
|
|
|
const [invoice, setInvoice] = useState("");
|
2023-04-13 18:43:43 +00:00
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
(async () => {
|
|
|
|
try {
|
|
|
|
const s = await api.listSubscriptions();
|
|
|
|
setSubs(s);
|
|
|
|
} catch (e) {
|
2023-04-17 20:33:55 +00:00
|
|
|
if (e instanceof SubscriptionError) {
|
|
|
|
setError(e);
|
2023-04-13 18:43:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
}, []);
|
|
|
|
|
2023-04-17 20:33:55 +00:00
|
|
|
async function renew(id: string) {
|
|
|
|
try {
|
|
|
|
const rsp = await api.renewSubscription(id);
|
|
|
|
setInvoice(rsp.pr);
|
|
|
|
} catch (e) {
|
|
|
|
if (e instanceof SubscriptionError) {
|
|
|
|
setError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-13 18:43:43 +00:00
|
|
|
if (subs === undefined) {
|
|
|
|
return <PageSpinner />;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<h2>
|
|
|
|
<FormattedMessage defaultMessage="Subscriptions" />
|
|
|
|
</h2>
|
|
|
|
{subs.map(a => {
|
|
|
|
const created = new Date(a.created);
|
|
|
|
const expires = new Date(a.expires);
|
|
|
|
const now = new Date();
|
|
|
|
const daysToExpire = Math.floor((expires.getTime() - now.getTime()) / 8.64e7);
|
|
|
|
const hoursToExpire = Math.floor((expires.getTime() - now.getTime()) / 3.6e6);
|
2023-04-17 20:33:55 +00:00
|
|
|
const isExpired = a.state === "expired";
|
|
|
|
const isNew = a.state === "new";
|
2023-04-13 18:43:43 +00:00
|
|
|
return (
|
|
|
|
<div key={a.id} className="card">
|
|
|
|
<div className="flex card-title">
|
|
|
|
<Icon name="badge" className="mr5" size={25} />
|
|
|
|
{mapPlanName(a.type)}
|
|
|
|
</div>
|
|
|
|
<div className="flex">
|
|
|
|
<p className="f-1">
|
|
|
|
<FormattedMessage defaultMessage="Created" />
|
|
|
|
:
|
|
|
|
<time dateTime={created.toISOString()}>
|
|
|
|
<FormattedDate value={created} dateStyle="full" />
|
|
|
|
</time>
|
|
|
|
</p>
|
|
|
|
{daysToExpire >= 1 && (
|
|
|
|
<p className="f-1">
|
|
|
|
<FormattedMessage defaultMessage="Expires" />
|
|
|
|
:
|
|
|
|
<time dateTime={expires.toISOString()}>
|
|
|
|
<FormattedMessage
|
|
|
|
defaultMessage="{n} days"
|
|
|
|
values={{
|
|
|
|
n: <FormattedNumber value={daysToExpire} maximumFractionDigits={0} />,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</time>
|
|
|
|
</p>
|
|
|
|
)}
|
|
|
|
{daysToExpire >= 0 && daysToExpire < 1 && (
|
|
|
|
<p className="f-1">
|
|
|
|
<FormattedMessage defaultMessage="Expires" />
|
|
|
|
:
|
|
|
|
<time dateTime={expires.toISOString()}>
|
|
|
|
<FormattedMessage
|
|
|
|
defaultMessage="{n} hours"
|
|
|
|
values={{
|
|
|
|
n: <FormattedNumber value={hoursToExpire} maximumFractionDigits={0} />,
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</time>
|
|
|
|
</p>
|
|
|
|
)}
|
2023-04-17 20:33:55 +00:00
|
|
|
{isExpired && (
|
2023-04-13 18:43:43 +00:00
|
|
|
<p className="f-1 error">
|
|
|
|
<FormattedMessage defaultMessage="Expired" />
|
|
|
|
</p>
|
|
|
|
)}
|
2023-04-17 20:33:55 +00:00
|
|
|
{isNew && (
|
|
|
|
<p className="f-1">
|
|
|
|
<FormattedMessage defaultMessage="Unpaid" />
|
|
|
|
</p>
|
|
|
|
)}
|
2023-04-13 18:43:43 +00:00
|
|
|
</div>
|
2023-04-17 20:33:55 +00:00
|
|
|
{(isExpired || isNew) && (
|
2023-04-13 18:43:43 +00:00
|
|
|
<div className="flex">
|
2023-04-17 20:33:55 +00:00
|
|
|
<AsyncButton onClick={() => renew(a.id)}>
|
|
|
|
{isExpired ? (
|
|
|
|
<FormattedMessage defaultMessage="Renew" />
|
|
|
|
) : (
|
|
|
|
<FormattedMessage defaultMessage="Pay Now" />
|
|
|
|
)}
|
|
|
|
</AsyncButton>
|
2023-04-13 18:43:43 +00:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
{subs.length === 0 && (
|
|
|
|
<p>
|
|
|
|
<FormattedMessage
|
|
|
|
defaultMessage="It looks like you dont have any subscriptions, you can get one {link}"
|
|
|
|
values={{
|
|
|
|
link: (
|
|
|
|
<Link to="/subscribe">
|
|
|
|
<FormattedMessage defaultMessage="here" />
|
|
|
|
</Link>
|
|
|
|
),
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</p>
|
|
|
|
)}
|
2023-04-17 20:33:55 +00:00
|
|
|
{error && <b className="error">{mapSubscriptionErrorCode(error)}</b>}
|
|
|
|
<SendSats
|
|
|
|
invoice={invoice}
|
|
|
|
show={invoice !== ""}
|
|
|
|
onClose={() => setInvoice("")}
|
|
|
|
title={formatMessage({
|
|
|
|
defaultMessage: "Renew subscription",
|
|
|
|
})}
|
|
|
|
/>
|
2023-04-13 18:43:43 +00:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|