Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor how prices are displayed on the subscription page #954

Merged
merged 3 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/components/subscription/current-plan-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const CurrentPlanDetails = () => {
You’re currently using the <b>{activeProduct?.name}</b> version of Shelf{" "}
{isTrialSubscription ? " on a free trial" : ""}.
</p>

<div>
{subscription?.canceled_at ? (
<>
Expand Down
35 changes: 24 additions & 11 deletions app/components/subscription/prices.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useLoaderData } from "@remix-run/react";
import type Stripe from "stripe";
import type { loader } from "~/routes/_layout+/settings.subscription";
import { shortenIntervalString } from "~/utils/shorten-interval-string";

Check warning on line 4 in app/components/subscription/prices.tsx

View workflow job for this annotation

GitHub Actions / ⬣ ESLint

'shortenIntervalString' is defined but never used. Allowed unused vars must match /^_/u
import { tw } from "~/utils/tw";
import { FREE_PLAN } from "./helpers";
import { PriceCta } from "./price-cta";
Expand Down Expand Up @@ -64,7 +64,12 @@
const isFreePlan = price.id != "free";
const features = price.product.metadata.features?.split(",") || [];

// icons to be mapped with different plans
const amount =
price.unit_amount != null
? price?.recurring?.interval === "year"
? price.unit_amount / 10
: price.unit_amount
: null;

return (
<div className="subscription-plan mb-12 w-full xl:mb-0 xl:max-w-[410px]">
Expand Down Expand Up @@ -96,16 +101,24 @@
</div>
) : null}
</div>
{price.unit_amount != null ? (
<div className=" mb-3 text-4xl font-semibold text-gray-900">
{(price.unit_amount / 100).toLocaleString("en-US", {
style: "currency",
currency: price.currency,
maximumFractionDigits: 0,
})}
{price.recurring ? (
<span>/{shortenIntervalString(price.recurring.interval)}</span>
) : null}
{amount != null ? (
<div className="mb-3 ">
<div className=" text-4xl font-semibold text-gray-900">
{(amount / 100).toLocaleString("en-US", {
style: "currency",
currency: price.currency,
maximumFractionDigits: 0,
})}
{price.recurring ? <span>/mo</span> : null}
</div>
<div className="text-gray-500">
{price?.recurring?.interval === "year" &&
`Billed annually ${(amount / 10).toLocaleString("en-US", {
style: "currency",
currency: price.currency,
maximumFractionDigits: 0,
})}`}
</div>
</div>
) : null}
<p className="min-h-[48px] text-base text-gray-600">
Expand Down
60 changes: 45 additions & 15 deletions app/routes/_layout+/settings.subscription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import { json, redirect } from "@remix-run/node";
import { Link, useLoaderData } from "@remix-run/react";
import { z } from "zod";
import { InfoIcon } from "~/components/icons/library";
import { Button } from "~/components/shared/button";
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "~/components/shared/tabs";
import { WarningBox } from "~/components/shared/warning-box";
import { CurrentPlanDetails } from "~/components/subscription/current-plan-details";
import { CustomerPortalForm } from "~/components/subscription/customer-portal-form";
import { Prices } from "~/components/subscription/prices";
Expand Down Expand Up @@ -196,21 +198,44 @@ export const handle = {
export default function UserPage() {
const { title, subTitle, prices, subscription } =
useLoaderData<typeof loader>();
const isLegacyPricing =
subscription?.items?.data[0]?.price?.metadata.legacy === "true";

return (
<>
<div className=" flex flex-col">
<div className="mb-8 mt-3 flex items-center gap-3 rounded border border-gray-300 p-4">
<div className="inline-flex items-center justify-center rounded-full border-[5px] border-solid border-primary-50 bg-primary-100 p-1.5 text-primary">
<InfoIcon />
<div className="mb-8 mt-3">
<div className="mb-2 flex items-center gap-3 rounded border border-gray-300 p-4">
<div className="inline-flex items-center justify-center rounded-full border-[5px] border-solid border-primary-50 bg-primary-100 p-1.5 text-primary">
<InfoIcon />
</div>
{!subscription ? (
<p className="text-[14px] font-medium text-gray-700">
You’re currently using the{" "}
<span className="font-semibold">FREE</span> version of Shelf
</p>
) : (
<CurrentPlanDetails />
)}
</div>
{!subscription ? (
<p className="text-[14px] font-medium text-gray-700">
You’re currently using the{" "}
<span className="font-semibold">FREE</span> version of Shelf
</p>
) : (
<CurrentPlanDetails />
{isLegacyPricing && (
<WarningBox>
<p>
You are on a{" "}
<Button
to="https://www.shelf.nu/legacy-plan-faq"
target="_blank"
variant="link"
>
legacy pricing plan
</Button>
. We have since updated our pricing plans. <br />
You can view the new pricing plans in the customer portal. If
you cancel your subscription, you will not be able to renew it.
<br />
For any questions - get in touch with support
</p>
</WarningBox>
)}
</div>

Expand All @@ -223,19 +248,24 @@ export default function UserPage() {
</div>

<Tabs
defaultValue={subscription?.items.data[0]?.plan.interval || "month"}
defaultValue={subscription?.items.data[0]?.plan.interval || "year"}
className="flex w-full flex-col"
>
<TabsList className="center mx-auto mb-8">
<TabsTrigger value="year">
Yearly{" "}
<span className="ml-2 rounded-[16px] bg-primary-50 px-2 py-1 text-xs font-medium text-primary-700">
Save 54%
</span>
</TabsTrigger>
<TabsTrigger value="month">Monthly</TabsTrigger>
<TabsTrigger value="year">Yearly (2 months free)</TabsTrigger>
</TabsList>
<TabsContent value="month">
<Prices prices={prices["month"]} />
</TabsContent>
<TabsContent value="year">
<Prices prices={prices["year"]} />
</TabsContent>
<TabsContent value="month">
<Prices prices={prices["month"]} />
</TabsContent>
</Tabs>
</div>
<SuccessfulSubscriptionModal />
Expand Down
Loading