Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/apps/web/app/modules/users/components/SubscriptionSettings.tsx
T

149 lines
5.6 KiB
TypeScript

import { useSubmit } from "react-router";
import { useTranslation } from "react-i18next";
import { PlanFeatureUsageDto } from "~/application/dtos/subscriptions/PlanFeatureUsageDto";
import MyProducts from "~/components/core/settings/subscription/MyProducts";
import MyInvoices from "~/components/core/settings/subscription/MyInvoices";
import SettingSection from "~/components/ui/sections/SettingSection";
import { TenantSubscriptionProductWithDetails } from "~/utils/db/subscriptions/tenantSubscriptionProducts.db.server";
import { TenantSubscriptionWithDetails } from "~/utils/db/tenantSubscriptions.db.server";
import { useRootData } from "~/utils/data/useRootData";
import type { CustomerBillingInvoiceDto } from "~/application/dtos/billing/CustomerBillingInvoiceDto";
import type { SubscriptionProductDto } from "~/application/dtos/subscriptions/SubscriptionProductDto";
import type { SubscriptionBillingPeriod } from "~/application/enums/subscriptions/SubscriptionBillingPeriod";
import PlansGrouped from "~/components/core/settings/subscription/plans/PlansGrouped";
import SeatUsageSection from "~/components/core/settings/subscription/SeatUsageSection";
import { Alert } from "~/ui/components/Alert";
import type { SeatUsageVM, SubscriptionBannerTone, SubscriptionBannerVM } from "@hivegrid/view-models";
function bannerVariant(tone: SubscriptionBannerTone): "success" | "warning" | "error" {
if (tone === "success") return "success";
if (tone === "warning") return "warning";
return "error";
}
export default function SubscriptionSettings({
mySubscription,
myInvoices,
availablePlans,
currenciesAndPeriod,
invoiceErrorKey,
permissions,
billingBanner,
seatUsage,
}: {
mySubscription: TenantSubscriptionWithDetails | null;
myFeatures: PlanFeatureUsageDto[];
myInvoices: CustomerBillingInvoiceDto[];
availablePlans: SubscriptionProductDto[];
currenciesAndPeriod: {
currencies: { value: string; options: string[] };
billingPeriods: { value: SubscriptionBillingPeriod; options: SubscriptionBillingPeriod[] };
};
invoiceErrorKey?: string | null;
permissions: { viewInvoices: boolean; manageSubscription: boolean };
billingBanner?: SubscriptionBannerVM;
seatUsage?: SeatUsageVM;
storageLimitGb?: number | null;
}) {
const { t } = useTranslation();
const submit = useSubmit();
const { csrf } = useRootData();
function onCancel(item: TenantSubscriptionProductWithDetails) {
const form = new FormData();
form.set("action", "cancel");
form.set("csrf", csrf ?? "");
form.set("tenant-subscription-product-id", item.id);
submit(form, {
method: "post",
});
}
// function onAddPaymentMethod() {
// const form = new FormData();
// form.set("action", "add-payment-method");
// submit(form, {
// method: "post",
// });
// }
return (
<div className="space-y-4" data-ui-id="ui.subscription.page">
{billingBanner?.status === "ready" ? (
<Alert
variant={bannerVariant(billingBanner.data.tone)}
notDismissible
title={t(billingBanner.data.titleKey)}
description={t(billingBanner.data.descriptionKey)}
data-ui-id="ui.subscription.statusBanner"
/>
) : null}
<SettingSection
title={t("settings.subscription.title")}
description={
<div className="flex flex-col space-y-1">
<div>{t("settings.subscription.description")}</div>
</div>
}
className=""
>
<MyProducts items={mySubscription?.products ?? []} onCancel={onCancel} />
</SettingSection>
{seatUsage && seatUsage.status !== "idle" && (
<>
<div className="hidden sm:block" aria-hidden="true">
<div className="py-4">
<div className="border-border border-t"></div>
</div>
</div>
<SettingSection title={t("settings.subscription.seats.title")} description={t("settings.subscription.seats.description")} className="">
<SeatUsageSection vm={seatUsage} />
</SettingSection>
</>
)}
{availablePlans.length > 0 && (
<>
<div className="hidden sm:block" aria-hidden="true">
<div className="py-4">
<div className="border-border border-t"></div>
</div>
</div>
<SettingSection title={t("settings.subscription.checkout.plans.title")} description={t("settings.subscription.checkout.plans.description")} className="">
<PlansGrouped
items={availablePlans}
tenantSubscription={mySubscription}
canSubmit={permissions.manageSubscription}
billingProviderCoupon={null}
currenciesAndPeriod={currenciesAndPeriod}
/>
</SettingSection>
</>
)}
{permissions.viewInvoices && (
<>
<div className="hidden sm:block" aria-hidden="true">
<div className="py-4">
<div className="border-border border-t"></div>
</div>
</div>
<SettingSection title={t("app.subscription.invoices.title")} description={t("app.subscription.invoices.description")} className="">
<MyInvoices items={myInvoices} error={invoiceErrorKey ? t(invoiceErrorKey) : null} />
</SettingSection>
</>
)}
{/* <SettingSection title={t("app.subscription.paymentMethods.title")} description={t("app.subscription.paymentMethods.description")}>
<div className="space-y-2">
<MyPaymentMethods items={myPaymentMethods} onAdd={onAddPaymentMethod} onDelete={onDeletePaymentMethod} />
</div>
</SettingSection> */}
</div>
);
}