CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/billing/subscription-grid.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { Row, Col } from "@cocalc/frontend/antd-bootstrap";
7
import { Component, Rendered, redux } from "../app-framework";
8
import { keys, intersection } from "lodash";
9
import { PeriodName } from "./types";
10
import { PlanInfo } from "./plan-info";
11
import { PROJECT_UPGRADES } from "@cocalc/util/schema";
12
13
interface Props {
14
periods: PeriodName[];
15
selected_plan?: string;
16
is_static?: boolean; // used for display mode
17
}
18
19
export class SubscriptionGrid extends Component<Props> {
20
private is_selected(plan: string): boolean {
21
if (this.props.selected_plan === plan) return true;
22
const period = this.props.periods[0];
23
if (period == null) return false; // doesn't happen
24
if (period.slice(0, 4) === "year") {
25
return this.props.selected_plan === `${plan}-year`;
26
} else if (period.slice(0, 4) === "week") {
27
return this.props.selected_plan === `${plan}-week`;
28
} else {
29
return false;
30
}
31
}
32
33
private click_on_plan(plan: string): void {
34
if (this.props.is_static) return;
35
const actions = redux.getActions("billing");
36
if (actions == null) return;
37
const period = this.props.periods[0];
38
if (period == null) return; // doesn't happen
39
actions.set_selected_plan(plan, period);
40
}
41
42
private render_plan_info(plan: string): Rendered {
43
return (
44
<PlanInfo
45
plan={plan}
46
periods={this.props.periods}
47
selected={this.is_selected(plan)}
48
on_click={
49
this.props.is_static ? undefined : () => this.click_on_plan(plan)
50
}
51
/>
52
);
53
}
54
55
private render_cols(row: string[], ncols: number): Rendered[] {
56
const width = 12 / ncols;
57
return row.map((plan) => (
58
<Col sm={width} key={plan}>
59
{this.render_plan_info(plan)}
60
</Col>
61
));
62
}
63
64
private render_rows(live_subscriptions: string[][], ncols): Rendered[] {
65
const v: Rendered[] = [];
66
for (const i in live_subscriptions) {
67
const row: string[] = live_subscriptions[i];
68
v.push(<Row key={i}>{this.render_cols(row, ncols)}</Row>);
69
}
70
return v;
71
}
72
73
public render(): Rendered {
74
const live_subscriptions: string[][] = [];
75
let ncols: number = 0; // max number of columns in any row
76
for (const row of PROJECT_UPGRADES.live_subscriptions) {
77
const v: string[] = [];
78
for (const x of row) {
79
const price_keys = keys(PROJECT_UPGRADES.subscription[x].price);
80
if (intersection(this.props.periods, price_keys).length > 0) {
81
ncols = Math.max(ncols, row.length); // this row matters.
82
v.push(x);
83
}
84
}
85
if (v.length > 0) {
86
live_subscriptions.push(v);
87
}
88
}
89
// Round up to nearest divisor of 12
90
if (ncols === 5) {
91
ncols = 6;
92
} else if (ncols >= 7) {
93
ncols = 12;
94
}
95
return <div>{this.render_rows(live_subscriptions, ncols)}</div>;
96
}
97
}
98
99