From 4ad036ac9b984d6c6d06aba3b261f31ea8a72eb9 Mon Sep 17 00:00:00 2001 From: Kieran Date: Thu, 8 Aug 2024 15:01:20 +0100 Subject: [PATCH] Add pay button --- index.html | 1 + src/App.tsx | 78 ++++++++++++++++++++++------------- src/api.ts | 28 +++++++++++++ src/components/cost.tsx | 14 +++++++ src/components/pay-button.css | 75 +++++++++++++++++++++++++++++++++ src/components/pay-button.tsx | 30 ++++++++++++++ src/components/vps-card.tsx | 16 +++++++ src/const.ts | 4 ++ 8 files changed, 218 insertions(+), 28 deletions(-) create mode 100644 src/api.ts create mode 100644 src/components/cost.tsx create mode 100644 src/components/pay-button.css create mode 100644 src/components/pay-button.tsx create mode 100644 src/components/vps-card.tsx create mode 100644 src/const.ts diff --git a/index.html b/index.html index 79c8e1c..7e9549d 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,7 @@
+ \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 8a7a25d..390fb63 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,37 +1,59 @@ +import { CostInterval, DiskType, MachineSpec } from "./api" +import VpsCard from "./components/vps-card" +import { GiB } from "./const" + export default function App() { + const offers: Array = [ + { + id: "2x2x80", + cpu: 2, + ram: 2 * GiB, + disk: { + type: DiskType.SSD, + size: 80 * GiB + }, + cost: { + interval: CostInterval.Month, + count: 3, + currency: "EUR", + } + }, + { + id: "4x4x160", + cpu: 4, + ram: 4 * GiB, + disk: { + type: DiskType.SSD, + size: 160 * GiB + }, + cost: { + interval: CostInterval.Month, + count: 5, + currency: "EUR", + } + }, + { + id: "8x8x400", + cpu: 8, + ram: 8 * GiB, + disk: { + type: DiskType.SSD, + size: 400 * GiB + }, + cost: { + interval: CostInterval.Month, + count: 12, + currency: "EUR", + } + } + ] return (
-

lnvps.com

+

LNVPS

VPS

-
-

2x2x80

-
    -
  • CPU: 2vCPU
  • -
  • RAM: 2GB
  • -
  • SSD: 80GB
  • -
-

3 EUR/mo

-
-
-

4x4x160

-
    -
  • CPU: 4vCPU
  • -
  • RAM: 4GB
  • -
  • SSD: 160GB
  • -
-

5 EUR/mo

-
-
-

8x8x400

-
    -
  • CPU: 8vCPU
  • -
  • RAM: 8GB
  • -
  • SSD: 400GB
  • -
-

12 EUR/mo

-
+ {offers.map(a => )}
All VPS come with 1x IPv4 and 1x IPv6 address and unmetered traffic. diff --git a/src/api.ts b/src/api.ts new file mode 100644 index 0000000..bd588f1 --- /dev/null +++ b/src/api.ts @@ -0,0 +1,28 @@ +export interface MachineSpec { + id: string; + cpu: number; + ram: number; + disk: { + type: DiskType; + size: number; + }; + cost: { + interval: CostInterval; + count: number; + currency: CostCurrency; + }; +} + +export enum DiskType { + HDD, + SSD, +} + +export enum CostInterval { + Hour, + Day, + Month, + Year, +} + +export type CostCurrency = "EUR" | "USD" | "BTC"; diff --git a/src/components/cost.tsx b/src/components/cost.tsx new file mode 100644 index 0000000..e356d66 --- /dev/null +++ b/src/components/cost.tsx @@ -0,0 +1,14 @@ +import { CostInterval, MachineSpec } from "../api"; + +export default function CostLabel({ cost }: { cost: MachineSpec["cost"] }) { + function intervalName(n: number) { + switch (n) { + case CostInterval.Hour: return "Hour" + case CostInterval.Day: return "Day" + case CostInterval.Month: return "Month" + case CostInterval.Year: return "Year" + } + } + + return <>{cost.count} {cost.currency}/{intervalName(cost.interval)} +} \ No newline at end of file diff --git a/src/components/pay-button.css b/src/components/pay-button.css new file mode 100644 index 0000000..38b1e34 --- /dev/null +++ b/src/components/pay-button.css @@ -0,0 +1,75 @@ +.btcpay-form { + display: inline-flex; + align-items: center; + justify-content: center; +} +.btcpay-form--inline { + flex-direction: row; +} +.btcpay-form--block { + flex-direction: column; +} +.btcpay-form--inline .submit { + margin-left: 15px; +} +.btcpay-form--block select { + margin-bottom: 10px; +} +.btcpay-form .btcpay-custom-container { + text-align: center; +} +.btcpay-custom { + display: flex; + align-items: center; + justify-content: center; +} +.btcpay-form .plus-minus { + cursor: pointer; + font-size: 25px; + line-height: 25px; + background: #dfe0e1; + height: 30px; + width: 45px; + border: none; + border-radius: 60px; + margin: auto 5px; + display: inline-flex; + justify-content: center; +} +.btcpay-form select { + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + color: currentColor; + background: transparent; + border: 1px solid transparent; + display: block; + padding: 1px; + margin-left: auto; + margin-right: auto; + font-size: 11px; + cursor: pointer; +} +.btcpay-form select:hover { + border-color: #ccc; +} +.btcpay-form option { + color: #000; + background: rgba(0, 0, 0, 0.1); +} +.btcpay-input-price { + -moz-appearance: textfield; + border: none; + box-shadow: none; + text-align: center; + font-size: 25px; + margin: auto; + border-radius: 5px; + line-height: 35px; + background: #fff; +} +.btcpay-input-price::-webkit-outer-spin-button, +.btcpay-input-price::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} diff --git a/src/components/pay-button.tsx b/src/components/pay-button.tsx new file mode 100644 index 0000000..1b46232 --- /dev/null +++ b/src/components/pay-button.tsx @@ -0,0 +1,30 @@ +import { MachineSpec } from "../api"; + +import "./pay-button.css" + +export default function VpsPayButton({ spec }: { spec: MachineSpec }) { + const serverUrl = "https://btcpay.v0l.io/api/v1/invoices"; + + function handleFormSubmit(event: React.FormEvent) { + event.preventDefault(); + const form = event.target as HTMLFormElement; + const xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function () { + if (this.readyState == 4 && this.status == 200 && this.responseText) { + window.btcpay.appendInvoiceFrame(JSON.parse(this.responseText).invoiceId); + } + }; + xhttp.open('POST', serverUrl, true); + xhttp.send(new FormData(form)); + } + + return
+ + + + + + +
+} \ No newline at end of file diff --git a/src/components/vps-card.tsx b/src/components/vps-card.tsx new file mode 100644 index 0000000..d34884a --- /dev/null +++ b/src/components/vps-card.tsx @@ -0,0 +1,16 @@ +import { DiskType, MachineSpec } from "../api"; +import CostLabel from "./cost"; +import VpsPayButton from "./pay-button"; + +export default function VpsCard({ spec }: { spec: MachineSpec }) { + return
+

{spec.id}

+
    +
  • CPU: {spec.cpu}vCPU
  • +
  • RAM: {spec.ram / 1024 / 1024 / 1024}GB
  • +
  • {spec.disk.type === DiskType.SSD ? "SSD" : "HDD"}: {spec.disk.size / 1024 / 1024 / 1024}GB
  • +
+

+ +
+} \ No newline at end of file diff --git a/src/const.ts b/src/const.ts new file mode 100644 index 0000000..8600cbe --- /dev/null +++ b/src/const.ts @@ -0,0 +1,4 @@ +export const KiB = 1024; +export const MiB = KiB * 1024; +export const GiB = MiB * 1024; +export const TiB = GiB * 1024; \ No newline at end of file