Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/billing/payment-methods.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Rendered, useActions, useState } from "../app-framework";6import { Button, Row, Col, Panel } from "../antd-bootstrap";7import { Icon } from "../components/icon";8import { Source } from "./types";9import { AddPaymentMethod } from "./add-payment-method";10import { PaymentMethod } from "./payment-method";11import { ErrorDisplay } from "../components/error-display";1213import { cmp } from "@cocalc/util/misc";1415interface Props {16sources?: { data: Source[] }; // could be undefined, if it is a customer and all sources are removed17default?: string;18}1920type State = "view" | "delete" | "add_new";2122export const PaymentMethods: React.FC<Props> = (props) => {23const [state, set_state] = useState<State>("view");24const [error, set_error] = useState<string>("");25const actions = useActions("billing");2627function add_payment_method(): void {28set_state("add_new");29}3031function render_add_payment_method(): Rendered {32if (state === "add_new") {33return <AddPaymentMethod on_close={() => set_state("view")} />;34}35}3637function render_add_payment_method_button(): Rendered {38return (39<Button40disabled={state !== "view"}41onClick={add_payment_method}42bsStyle="primary"43className="pull-right"44>45<Icon name="plus-circle" /> Add payment method...46</Button>47);48}4950function render_header(): Rendered {51return (52<Row>53<Col sm={6}>54<Icon name="credit-card" /> Payment methods55</Col>56<Col sm={6}>{render_add_payment_method_button()}</Col>57</Row>58);59}6061function set_as_default(id: string): void {62actions.set_as_default_payment_method(id);63}6465function delete_method(id: string): void {66actions.delete_payment_method(id);67}6869function render_payment_method(source: Source): Rendered {70if (source.object != "card") {71// TODO: non credit cards not yet supported.72// These *do* arise naturally already in cocalc, e.g., when you pay via73// for an invoice with a failing payment directly on the stripe page74// for your invoice.75return;76}77return (78<PaymentMethod79key={source.id}80source={source}81default={source.id === props.default}82set_as_default={() => set_as_default(source.id)}83delete_method={() => delete_method(source.id)}84/>85);86}8788function render_payment_methods(): undefined | Rendered[] {89// this happens, when it is a customer but all credit cards are deleted!90if (props.sources == null) {91return;92}93// Always sort sources in the same order. This way when you select94// a default source, they don't get reordered, which is really confusing.95props.sources.data.sort((a, b) => cmp(a.id, b.id));96return props.sources.data.map((source) => render_payment_method(source));97}9899function render_error(): Rendered {100if (error) {101return <ErrorDisplay error={error} onClose={() => set_error("")} />;102}103}104105return (106<Panel header={render_header()}>107{render_error()}108{state == "add_new" ? render_add_payment_method() : undefined}109{render_payment_methods()}110</Panel>111);112};113114115