From 2879d77e3d1b6335d9a35c03e18a4ea0d03f2946 Mon Sep 17 00:00:00 2001 From: Jon Ziebell Date: Sun, 16 Oct 2022 21:40:50 -0400 Subject: [PATCH] New contribute page is ready for testing --- api/stripe.php | 50 +++ api/stripe_api_cache.php | 8 + api/stripe_api_log.php | 8 + api/stripe_event.php | 17 + api/stripe_payment_link.php | 94 +++++ css/dashboard.css | 8 +- img/merchandise/sticker_logo.png | Bin 0 -> 7942 bytes img/merchandise/sticker_logo_text.png | Bin 0 -> 15313 bytes js/beestat/setting.js | 4 +- js/beestat/user.js | 33 +- js/component/card/contribute.js | 442 +++++++++++++---------- js/component/card/contribute_benefits.js | 58 +++ js/component/card/contribute_status.js | 237 ++++++++++++ js/component/card/merchandise.js | 130 +++++++ js/component/card/settings.js | 33 ++ js/js.php | 3 + js/layer/contribute.js | 22 +- js/layer/load.js | 28 ++ 18 files changed, 969 insertions(+), 206 deletions(-) create mode 100644 api/stripe.php create mode 100644 api/stripe_api_cache.php create mode 100644 api/stripe_api_log.php create mode 100644 api/stripe_event.php create mode 100644 api/stripe_payment_link.php create mode 100644 img/merchandise/sticker_logo.png create mode 100644 img/merchandise/sticker_logo_text.png create mode 100644 js/component/card/contribute_benefits.js create mode 100644 js/component/card/contribute_status.js create mode 100644 js/component/card/merchandise.js diff --git a/api/stripe.php b/api/stripe.php new file mode 100644 index 0000000..3099070 --- /dev/null +++ b/api/stripe.php @@ -0,0 +1,50 @@ + [], + 'public' => [] + ]; + + protected static $log_mysql = 'all'; + + protected static $cache = false; + protected static $cache_for = null; + + /** + * Send an API call off to Stripe + * + * @param string $method HTTP Method. + * @param string $endpoint API Endpoint. + * @param array $data API request data. + * + * @throws Exception If Stripe did not return valid JSON. + * + * @return array The Stripe response. + */ + public function stripe_api($method, $endpoint, $data) { + $curl_response = $this->curl([ + 'url' => $this->setting->get('stripe_base_url') . $endpoint, + 'post_fields' => http_build_query($data), + 'method' => $method, + 'header' => [ + 'Authorization: Basic ' . base64_encode($this->setting->get('stripe_secret_key') . ':'), + 'Content-Type: application/x-www-form-urlencoded' + ] + ]); + + $response = json_decode($curl_response, true); + + if ($response === null) { + throw new cora\exception('Invalid JSON', 10900); + } + + return $response; + } +} diff --git a/api/stripe_api_cache.php b/api/stripe_api_cache.php new file mode 100644 index 0000000..2bfb77a --- /dev/null +++ b/api/stripe_api_cache.php @@ -0,0 +1,8 @@ + [ + 'read_id' + ], + 'public' => [] + ]; + +} diff --git a/api/stripe_payment_link.php b/api/stripe_payment_link.php new file mode 100644 index 0000000..eba58a4 --- /dev/null +++ b/api/stripe_payment_link.php @@ -0,0 +1,94 @@ + [ + 'get', + 'open' + ], + 'public' => [] + ]; + + public static $user_locked = false; + + /** + * Get a stripe_payment_link for the specified attributes. If none exists, + * create. + * + * @param array $attributes + * + * @return array + */ + public function get($attributes) { + $stripe_payment_link = parent::get([ + 'amount' => $attributes['amount'], + 'currency' => $attributes['currency'], + 'interval' => $attributes['interval'] + ]); + + if($stripe_payment_link === null) { + $price = $this->api( + 'stripe', + 'stripe_api', + [ + 'method' => 'POST', + 'endpoint' => 'prices', + 'data' => [ + 'product' => $this->setting->get('stripe_product_id'), + 'unit_amount' => $attributes['amount'], + 'currency' => $attributes['currency'], + 'recurring[interval]' => $attributes['interval'] + ] + ] + ); + + $payment_link = $this->api( + 'stripe', + 'stripe_api', + [ + 'method' => 'POST', + 'endpoint' => 'payment_links', + 'data' => [ + 'line_items[0][price]' => $price['id'], + 'line_items[0][quantity]' => '1' + ] + ] + ); + + return $this->create([ + 'amount' => $attributes['amount'], + 'currency' => $attributes['currency'], + 'interval' => $attributes['interval'], + 'url' => $payment_link['url'] + ]); + } else { + return $stripe_payment_link; + } + } + + /** + * Open a Stripe link. This exists because in JS it would be a popup to run + * an API call to get the link, then do window.open after. This lets you + * just do a window.open directly to this endpoint. + * + * @param array $attributes + */ + public function open($attributes) { + $stripe_payment_link = $this->get($attributes); + + $user = $this->api('user', 'get', $this->session->get_user_id()); + $url = $stripe_payment_link['url'] . + '?prefilled_email=' . $user['email_address'] . + '&client_reference_id=' . $user['user_id']; + + header('Location: ' . $url); + die(); + } + +} diff --git a/css/dashboard.css b/css/dashboard.css index 83e27eb..781678b 100644 --- a/css/dashboard.css +++ b/css/dashboard.css @@ -454,6 +454,7 @@ input[type=range]::-moz-range-thumb { .icon.code_tags:before { content: "\F0174"; } .icon.cog:before { content: "\F0493"; } .icon.credit_card_lock:before { content: "\F18E7"; } +.icon.credit_card_settings:before { content: "\F0FF5"; } .icon.currency_usd:before { content: "\F01C1"; } .icon.delete:before { content: "\F01B4"; } .icon.dots_vertical:before { content: "\F01D9"; } @@ -468,6 +469,7 @@ input[type=range]::-moz-range-thumb { .icon.fast_forward:before { content: "\F0211"; } .icon.fire:before { content: "\F0238"; } .icon.floor_plan:before { content: "\F0821"; } +.icon.forum:before { content: "\F028C"; } .icon.gift:before { content: "\F0E44"; } .icon.google_play:before { content: "\F02BC"; } .icon.grid:before { content: "\F02C1"; } @@ -481,6 +483,8 @@ input[type=range]::-moz-range-thumb { .icon.information:before { content: "\F02FC"; } .icon.key:before { content: "\F0306"; } .icon.label:before { content: "\F0315"; } +.icon.label:before { content: "\F0315"; } +.icon.label_off:before { content: "\F0ACB"; } .icon.layers:before { content: "\F0328"; } .icon.layers_plus:before { content: "\F0E4D"; } .icon.link_off:before { content: "\F0338"; } @@ -516,6 +520,7 @@ input[type=range]::-moz-range-thumb { .icon.numeric_8_box:before { content: "\F03B9"; } .icon.numeric_9:before { content: "\F0B42"; } .icon.numeric_9_box:before { content: "\F03BC"; } +.icon.octagram:before { content: "\F06F9"; } .icon.open_in_new:before { content: "\F03CC"; } .icon.patreon:before { content: "\F0882"; } .icon.pause:before { content: "\F03E4"; } @@ -529,6 +534,7 @@ input[type=range]::-moz-range-thumb { .icon.restart:before { content: "\F0709"; } .icon.restart_off:before { content: "\F0D95"; } .icon.snowflake:before { content: "\F0717"; } +.icon.sticker_emoji:before { content: "\F0785"; } .icon.swap_horizontal:before { content: "\F04E1"; } .icon.thermometer:before { content: "\F050F"; } .icon.thermostat:before { content: "\F0393"; } @@ -558,8 +564,6 @@ input[type=range]::-moz-range-thumb { .icon.wifi_strength_1_alert:before { content: "\F0920"; } .icon.wifi_strength_4:before { content: "\F0928"; } .icon.zigbee:before { content: "\F0D41"; } -.icon.label:before { content: "\F0315"; } -.icon.label_off:before { content: "\F0ACB"; } .icon.f16:before { font-size: 16px; } .icon.f24:before { font-size: 24px; } diff --git a/img/merchandise/sticker_logo.png b/img/merchandise/sticker_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d35c08f352d7e2e991d83e907ce4ab5f2c187202 GIT binary patch literal 7942 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 ThbLdY^pF%~RpE6q<`Mq`x8A)a literal 0 HcmV?d00001 diff --git a/img/merchandise/sticker_logo_text.png b/img/merchandise/sticker_logo_text.png new file mode 100644 index 0000000000000000000000000000000000000000..16dd989945ea82d2b1a5a6caa7e017ad3b3f2acb GIT binary patch literal 15313 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'environment') === 'dev' || $setting->get('environment') === 'd echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; + echo '' . PHP_EOL; + echo '' . PHP_EOL; + echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; diff --git a/js/layer/contribute.js b/js/layer/contribute.js index 596e10a..5d6b7dd 100644 --- a/js/layer/contribute.js +++ b/js/layer/contribute.js @@ -34,11 +34,27 @@ beestat.layer.contribute.prototype.decorate_ = function(parent) { cards.push([ { 'card': new beestat.component.card.contribute(), - 'size': 9 + 'size': 8 }, { - 'card': new beestat.component.card.contribute(), - 'size': 3 + 'card': new beestat.component.card.contribute_benefits(), + 'size': 4 + } + ]); + + // History + cards.push([ + { + 'card': new beestat.component.card.contribute_status(), + 'size': 12 + } + ]); + + // Merchandise + cards.push([ + { + 'card': new beestat.component.card.merchandise(), + 'size': 12 } ]); diff --git a/js/layer/load.js b/js/layer/load.js index dc950ab..51d8143 100644 --- a/js/layer/load.js +++ b/js/layer/load.js @@ -127,6 +127,13 @@ beestat.layer.load.prototype.decorate_ = function(parent) { 'runtime_thermostat_summary' ); + api.add_call( + 'stripe_event', + 'read_id', + {}, + 'stripe_event' + ); + api.set_callback(function(response) { beestat.cache.set('user', response.user); @@ -145,6 +152,7 @@ beestat.layer.load.prototype.decorate_ = function(parent) { beestat.cache.set('floor_plan', response.floor_plan); beestat.cache.set('announcement', response.announcement); beestat.cache.set('runtime_thermostat_summary', response.runtime_thermostat_summary); + beestat.cache.set('stripe_event', response.stripe_event); // Set the active thermostat_id if this is your first time visiting. if (beestat.setting('thermostat_id') === undefined) { @@ -203,6 +211,26 @@ beestat.layer.load.prototype.decorate_ = function(parent) { ); } + // Currency (USD is default) + const currency_map = { + 'CAN': 'cad', + 'AUS': 'aud', + 'GBR': 'gbp' + }; + if ( + beestat.setting('units.currency') === undefined && + thermostat.address_id !== null && + beestat.address.is_valid(thermostat.address_id) === true + ) { + const address = beestat.cache.address[thermostat.address_id]; + if (currency_map[address.normalized.components.country_iso_3] !== undefined) { + beestat.setting( + 'units.currency', + currency_map[address.normalized.components.country_iso_3] + ); + } + } + // Rename series if there are multiple stages. if (beestat.thermostat.get_stages(thermostat.thermostat_id, 'heat') > 1) { beestat.series.compressor_heat_1.name = 'Heat 1';