Path: blob/master/src/packages/next/pages/pricing/subscriptions.tsx
1450 views
/*1* This file is part of CoCalc: Copyright © 2022 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Alert, Layout, List } from "antd";6import dayjs from "dayjs";78import { Icon, IconName } from "@cocalc/frontend/components/icon";9import { LicenseIdleTimeouts } from "@cocalc/util/consts/site-license";10import { compute_cost } from "@cocalc/util/licenses/purchase/compute-cost";11import {12CURRENT_VERSION,13discount_monthly_pct,14discount_yearly_pct,15MIN_QUOTE,16} from "@cocalc/util/licenses/purchase/consts";17import { PurchaseInfo } from "@cocalc/util/licenses/purchase/types";18import { money } from "@cocalc/util/licenses/purchase/utils";19import { COLORS } from "@cocalc/util/theme";20import Footer from "components/landing/footer";21import Head from "components/landing/head";22import Header from "components/landing/header";23import PricingItem, { Line } from "components/landing/pricing-item";24import { Paragraph, Title } from "components/misc";25import A from "components/misc/A";26import {27applyLicense,28listedPrices,29pricingQuestions,30} from "components/share/pricing";31import { LinkToStore, StoreConf } from "components/store/link";32import { MAX_WIDTH } from "lib/config";33import { Customize } from "lib/customize";34import withCustomize from "lib/with-customize";3536import type { JSX } from "react";3738function addMonth(date: Date): Date {39return dayjs(date).add(30, "days").add(12, "hours").toDate();40}4142interface Item {43title: string;44icon: IconName;45projects: number;46disk: number;47shared_ram: number;48shared_cores: number;49academic?: boolean;50uptime?: string;51monthly: number;52yearly: number;53conf: StoreConf;54}5556const now = new Date();5758const hobby: Item = (() => {59const conf = {60run_limit: 2,61disk: 3,62ram: 2,63cpu: 1,64uptime: "short",65user: "academic",66} as const;6768const info: PurchaseInfo = {69version: CURRENT_VERSION,70type: "quota",71user: conf.user,72upgrade: "custom",73quantity: conf.run_limit,74subscription: "monthly",75start: now,76end: addMonth(now),77custom_ram: conf.ram,78custom_cpu: conf.cpu,79custom_disk: conf.disk,80custom_member: true,81custom_dedicated_ram: 0,82custom_dedicated_cpu: 0,83custom_uptime: conf.uptime,84};8586const priceM = compute_cost(info);87const priceY = compute_cost({ ...info, subscription: "yearly" });8889return {90title: "Hobbyist",91icon: "battery-quarter",92projects: conf.run_limit,93shared_ram: conf.ram,94shared_cores: conf.cpu,95disk: conf.disk,96academic: true,97uptime: LicenseIdleTimeouts[conf.uptime].labelShort,98monthly: priceM.cost,99yearly: priceY.cost,100conf,101};102})();103104const academic: Item = (() => {105const conf = {106run_limit: 3,107disk: 10,108ram: 5,109cpu: 2,110uptime: "day",111user: "academic",112} as const;113114const info: PurchaseInfo = {115version: CURRENT_VERSION,116type: "quota",117user: conf.user,118upgrade: "custom",119quantity: conf.run_limit,120subscription: "monthly",121start: now,122end: addMonth(now),123custom_ram: conf.ram,124custom_cpu: conf.cpu,125custom_disk: conf.disk,126custom_member: true,127custom_dedicated_ram: 0,128custom_dedicated_cpu: 0,129custom_uptime: conf.uptime,130};131132const priceM = compute_cost(info);133const priceY = compute_cost({ ...info, subscription: "yearly" });134135return {136title: "Academic Researcher Group",137icon: "battery-half",138projects: conf.run_limit,139shared_ram: conf.ram,140shared_cores: conf.cpu,141disk: conf.disk,142dedicated_cores: 0,143academic: true,144uptime: LicenseIdleTimeouts[conf.uptime].labelShort,145monthly: priceM.cost,146yearly: priceY.cost,147conf,148};149})();150151const business: Item = (() => {152const conf = {153run_limit: 5,154disk: 5,155ram: 4,156cpu: 1,157uptime: "medium",158user: "business",159} as const;160161const info: PurchaseInfo = {162version: CURRENT_VERSION,163type: "quota",164user: conf.user,165upgrade: "custom",166quantity: conf.run_limit,167subscription: "monthly",168start: now,169end: addMonth(now),170custom_ram: conf.ram,171custom_cpu: conf.cpu,172custom_disk: conf.disk,173custom_member: true,174custom_dedicated_ram: 0,175custom_dedicated_cpu: 0,176custom_uptime: conf.uptime,177};178179const priceM = compute_cost(info);180const priceY = compute_cost({ ...info, subscription: "yearly" });181182return {183title: "Business Working Group",184icon: "battery-full",185projects: conf.run_limit,186shared_ram: conf.ram,187shared_cores: conf.cpu,188disk: conf.disk,189academic: false,190uptime: LicenseIdleTimeouts[conf.uptime].labelShort,191monthly: priceM.cost,192yearly: priceY.cost,193conf,194};195})();196197const data: Item[] = [hobby, academic, business];198199function dedicated(): JSX.Element {200return (201<Alert202style={{ margin: "15px 0" }}203message="Dedicated Virtual Machines"204description={205<span style={{ fontSize: "11pt" }}>206For more intensive workloads you can also rent a{" "}207<A href="/pricing/dedicated">dedicated virtual machine or disk</A>.208</span>209}210type="info"211showIcon212/>213);214}215216export default function Subscriptions({ customize }) {217const { siteName } = customize;218return (219<Customize value={customize}>220<Head title={`${siteName} – Pricing – Subscriptions`} />221<Layout>222<Header page="pricing" subPage="subscriptions" />223<Layout.Content224style={{225backgroundColor: "white",226}}227>228<Body />229<Footer />230</Layout.Content>231</Layout>232</Customize>233);234}235236function Body(): JSX.Element {237return (238<div239style={{240maxWidth: MAX_WIDTH,241margin: "15px auto",242padding: "15px",243backgroundColor: "white",244}}245>246<Title level={1} style={{ textAlign: "center" }}>247<Icon name="calendar" style={{ marginRight: "30px" }} /> CoCalc -248Subscriptions249</Title>250<a id="subscriptions"></a>251<Paragraph>252Initially, you start using CoCalc under a{" "}253<A href="https://doc.cocalc.com/trial.html">free trial plan</A> in order254to test out the service. If CoCalc works for you, please purchase a255license.256</Paragraph>257<Paragraph>258A subscription provides you with a{" "}259<A href="https://doc.cocalc.com/licenses.html">license key</A> for{" "}260<A href="https://doc.cocalc.com/project-settings.html#licenses">261upgrading your projects262</A>{" "}263or other projects where you are a collaborator — everyone using an264upgraded project benefits equally. Such a{" "}265<A href="/billing/subscriptions">subscription</A>{" "}266<b>automatically renews</b> at the end of each period. You can{" "}267<A href="/billing/subscriptions">268<b>cancel at any time</b>269</A>270.271</Paragraph>272273{applyLicense()}274275<Title level={2}>Examples</Title>276<Paragraph>277We list three typical configurations below, which you can{" "}278<A href="/store/site-license">modify and purchase here</A>. All279parameters can be adjusted to fit your needs. Listed upgrades are for280each project. Exact prices may vary. Below ${MIN_QUOTE}, only online281purchases are available (no purchase orders). Subscriptions receive a{" "}282{discount_monthly_pct}% discount for monthly and {discount_yearly_pct}%283for yearly periods.284</Paragraph>285<List286grid={{ gutter: 15, column: 3, xs: 1, sm: 1 }}287dataSource={data}288renderItem={(item) => (289<PricingItem title={item.title} icon={item.icon}>290<Line amount={item.projects} desc="Projects" />291<Line amount={item.shared_ram} desc="Shared RAM per project" />292<Line amount={item.shared_cores} desc="Shared CPU per project" />293<Line amount={item.disk} desc="Disk space per project" />294<Line amount={item.uptime} desc="Idle timeout" />295<Line amount={"∞"} desc="Collaborators" />296{item.academic ? (297<Line amount="40%" desc="Academic discount" />298) : (299<Line amount="" desc="" />300)}301302<br />303<br />304<div>305<span306style={{307fontWeight: "bold",308fontSize: "18pt",309color: COLORS.GRAY_DD,310}}311>312{money(item.monthly, true)}313</span>{" "}314/ month315</div>316<div>317<span318style={{319fontWeight: "bold",320fontSize: "18pt",321color: COLORS.GRAY_DD,322}}323>324{money(item.yearly, true)}325</span>{" "}326/ year327</div>328<LinkToStore conf={item.conf} />329</PricingItem>330)}331/>332{listedPrices()}333{pricingQuestions()}334{dedicated()}335</div>336);337}338339export async function getServerSideProps(context) {340return await withCustomize({ context });341}342343344