account wip

This commit is contained in:
ntr 2019-08-09 22:48:58 +10:00
parent fe56528b3f
commit 89d2b39823
15 changed files with 336 additions and 123 deletions

View File

@ -0,0 +1,58 @@
@import 'colours.less';
.account-page {
height: 100%;
display: grid;
grid-template-rows: minmax(min-content, 2fr) 1fr;
grid-template-columns: 1fr;
grid-template-areas:
"team"
"account";
button {
display: block;
height: 3em;
width: 75%;
}
input {
width: 75%;
height: 3em;
display: block;
}
.team {
grid-area: team;
/* poor man's <hr>*/
border-bottom: 0.1em solid #444;
}
.account {
margin: 2em 2em 0 0;
grid-area: account;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap: 0 1em;
}
}
.stripe-btn {
background: @yellow;
color: black;
border-radius: 2px;
border-width: 0;
&:active, &:focus, &:hover {
color: black;
}
&[disabled] {
border: 1px solid @yellow;
color: @yellow;
background: black;
}
}

View File

@ -4,6 +4,7 @@
@blue: #3050f8;
@white: #f5f5f5; // whitesmoke
@purple: #9355b5; // 6lack - that far cover
@yellow: #ffa100;
@black: black;
@gray: #222;

View File

@ -1,3 +1,4 @@
@import 'colours.less';
/* GAME */
.game {

View File

@ -90,6 +90,10 @@ nav {
padding-left: 2em;
margin-right: 2em;
max-height: 100%;
h1 {
margin-bottom: 0.5em;
}
}
nav h2:first-child {
@ -166,17 +170,17 @@ button, input {
transition-duration: 0.25s;
transition-delay: 0;
transition-timing-function: ease;
}
button:hover {
color: whitesmoke;
border-color: @gray-hover;
}
&:hover {
color: whitesmoke;
border-color: @gray-hover;
}
button:focus {
/*colour necesary to bash skellington*/
color: @gray-focus;
border-color: @gray-focus;
&:focus {
/*colour necesary to bash skellington*/
color: @gray-focus;
border-color: @gray-focus;
}
}
a {
@ -327,16 +331,12 @@ header {
margin-bottom: 1.5em;
}
.account {
margin: 1em 0;
}
.header-title {
flex: 1;
letter-spacing: 0.05em;
}
.account-status {
.account-info {
display: flex;
}
@ -346,7 +346,7 @@ header {
display: inline;
}
.account-status svg {
.account-info svg {
margin: 0.5em 0 0 1em;
height: 1em;
background-color: black;
@ -481,6 +481,10 @@ header {
display: grid;
grid-template-columns: 1fr 1fr;
h1 {
margin-bottom: 0.5em;
}
.list {
letter-spacing: 0.25em;
text-transform: uppercase;
@ -504,19 +508,6 @@ header {
font-size: 1.2em;
}
.stripe-btn {
width: 100%;
padding: 0 0.5em;
margin: 0.25em 0;
background: whitesmoke;
color: black;
border-radius: 2px;
}
.stripe-btn:hover {
color: black;
}
.play-btn {
font-size: 150%;
}
@ -566,6 +557,11 @@ main .top button {
width: 100%;
}
.credits {
color: @yellow;
font-weight: 800;
}
.timer-container {
display: flex;
flex: 1 1 100%;

View File

@ -3,6 +3,7 @@ require('./assets/styles/instance.less');
require('./assets/styles/vbox.less');
require('./assets/styles/game.less');
require('./assets/styles/controls.less');
require('./assets/styles/account.less');
require('./assets/styles/styles.mobile.css');
require('./assets/styles/instance.mobile.css');

View File

@ -0,0 +1,90 @@
const { connect } = require('preact-redux');
const preact = require('preact');
const { postData } = require('./../utils');
const actions = require('../actions');
const addState = connect(
function receiveState(state) {
const {
account,
ping,
} = state;
function logout() {
postData('/logout').then(() => window.location.reload(true));
}
return {
account,
ping,
logout,
};
},
);
function AccountStatus(args) {
const {
account,
ping,
logout,
} = args;
if (!account) return null;
return (
<section class='account'>
<div>
<h1>{account.name}</h1>
<dl>
<dt>Subscription</dt>
<dd>{account.subscribed ? 'some date' : 'unsubscribed'}</dd>
</dl>
<button onClick={() => logout()}>Logout</button>
</div>
<form>
<label for="email">Update Email:</label>
<input
class="login-input"
disabled
type="email"
name="current"
placeholder={account.email || 'no email set'}
/>
<input
class="login-input"
type="email"
name="email"
placeholder="new email"
/>
<button>Update</button>
</form>
<form>
<label for="password">Change Password:</label>
<input
class="login-input"
type="password"
name="current"
placeholder="current"
/>
<input
class="login-input"
type="password"
name="new"
placeholder="new password"
/>
<input
class="login-input"
type="password"
name="confirm"
placeholder="confirm"
/>
<button>Change</button>
</form>
</section>
);
}
module.exports = addState(AccountStatus);

View File

@ -0,0 +1,33 @@
const { connect } = require('preact-redux');
const preact = require('preact');
const Team = require('./team');
const AccountManagement = require('./account.management');
const addState = connect(
function receiveState(state) {
const {
ws,
account,
} = state;
return {
account,
};
},
);
function Account(args) {
const {
account,
} = args;
return (
<main class="account-page">
<Team />
<AccountManagement />
</main>
);
}
module.exports = addState(Account);

View File

@ -1,9 +1,7 @@
const { connect } = require('preact-redux');
const preact = require('preact');
const { Elements, injectStripe } = require('react-stripe-elements');
const { saw } = require('./shapes');
const { postData } = require('./../utils');
const actions = require('../actions');
function pingColour(ping) {
@ -12,55 +10,6 @@ function pingColour(ping) {
return 'red';
}
function BitsBtn(args) {
const {
stripe,
account,
} = args;
function subscribeClick(e) {
stripe.redirectToCheckout({
items: [{plan: 'plan_FGmRwawcOJJ7Nv', quantity: 1}],
successUrl: 'http://localhost/api/payments/success',
cancelUrl: 'http://localhost/api/payments/cancel',
clientReferenceId: account.id
});
}
function bitsClick(e) {
stripe.redirectToCheckout({
items: [{sku: 'sku_FHUfNEhWQaVDaT', quantity: 1}],
successUrl: 'http://localhost/payments/success',
cancelUrl: 'http://localhost/payments/cancel',
clientReferenceId: account.id
});
}
const subscription = account.subscribed
? <h3 class="account-header">Subscribed</h3>
: <button
onClick={subscribeClick}
class="stripe-btn"
role="link">
Subscribe
</button>;
return (
<div>
<div id="error-message"></div>
{subscription}
<button
onClick={bitsClick}
class="stripe-btn"
role="link">
Get Credits
</button>
</div>
);
}
const StripeBitsBtn = injectStripe(BitsBtn);
const addState = connect(
function receiveState(state) {
const {
@ -68,23 +17,18 @@ const addState = connect(
ping,
} = state;
function logout() {
postData('/logout').then(() => window.location.reload(true));
}
return {
account,
ping,
logout,
};
},
function receiveDispatch(dispatch) {
function selectConstructs() {
return dispatch(actions.setNav('team'));
function accountPage() {
return dispatch(actions.setNav('account'));
}
return {
selectConstructs,
accountPage,
};
}
);
@ -94,25 +38,20 @@ function AccountStatus(args) {
const {
account,
ping,
logout,
selectConstructs,
accountPage,
} = args;
if (!account) return null;
return (
<div class="account">
<div class="account-status">
<div class="account-status">
<div class="account-info">
<h2 class="account-header">{account.name}</h2>
{saw(pingColour(ping))}
<div class="ping-text">{ping}ms</div>
</div>
<h3 class="account-header">{`¤${account.balance}`}</h3>
<Elements>
<StripeBitsBtn account={account} />
</Elements>
<button onClick={() => selectConstructs()}>Constructs </button>
<button onClick={() => logout()}>Logout</button>
<h3 class="account-header credits">{`¤${account.balance}`}</h3>
<button onClick={() => accountPage()}> account</button>
</div>
);
}

View File

@ -34,7 +34,7 @@ function Controls(args) {
if (game) return <GameCtrl />;
if (instance) return <InstanceCtrl />;
if (nav === 'play' || !nav) return <PlayCtrl />
if (nav === 'team' || !nav) return <TeamCtrl />
if (nav === 'team' || nav === 'account') return <TeamCtrl />
return false;
}

View File

@ -1,8 +1,11 @@
const { connect } = require('preact-redux');
const { Elements } = require('react-stripe-elements');
const preact = require('preact');
const toast = require('izitoast');
const actions = require('./../actions');
const StripeBtns = require('./stripe.buttons');
const addState = connect(
function receiveState(state) {
@ -63,15 +66,18 @@ function Inventory(args) {
return (
<div class="inventory">
<div>
<h1>¤ {account.balance}</h1>
<h1>Shop</h1>
<Elements>
<StripeBtns account={account} />
</Elements>
<div class='list'>
{shop.owned.map(useMtx)}
{shop.available.map(availableMtx)}
</div>
</div>
<div>
<h1>Shop</h1>
<h1 class="credits">¤ {account.balance}</h1>
<div class='list'>
{shop.available.map(availableMtx)}
{shop.owned.map(useMtx)}
</div>
</div>
</div>

View File

@ -7,6 +7,7 @@ const Game = require('./game');
const Instance = require('./instance.component');
const Team = require('./team');
const Play = require('./play');
const Account = require('./account.page');
const addState = connect(
state => {
@ -38,6 +39,7 @@ function Main(props) {
if (nav === 'transition') return false;
if (nav === 'play') return <Play />;
if (nav === 'team') return <Team />;
if (nav === 'account') return <Account />;
return (
<Play />

View File

@ -0,0 +1,54 @@
const preact = require('preact');
const { injectStripe } = require('react-stripe-elements');
function BitsBtn(args) {
const {
stripe,
account,
} = args;
function subscribeClick() {
stripe.redirectToCheckout({
items: [{ plan: 'plan_FGmRwawcOJJ7Nv', quantity: 1 }],
successUrl: 'http://localhost',
cancelUrl: 'http://localhost',
clientReferenceId: account.id,
});
}
function bitsClick() {
stripe.redirectToCheckout({
items: [{ sku: 'sku_FHUfNEhWQaVDaT', quantity: 1 }],
successUrl: 'http://localhost',
cancelUrl: 'http://localhost',
clientReferenceId: account.id,
});
}
const subscription = account.subscribed
? <button
class="stripe-btn"
disabled>
Subscribed
</button>
: <button
onClick={subscribeClick}
class="stripe-btn"
role="link">
Subscribe
</button>;
return (
<div class='list'>
{subscription}
<button
onClick={bitsClick}
class="stripe-btn"
role="link">
Get Credits
</button>
<div id="error-message"></div>
</div>
);
}
module.exports = injectStripe(BitsBtn);

View File

@ -89,10 +89,10 @@ function Team(args) {
.map(i => <SpawnButton key={constructs.length + i} spawn={() => sendConstructSpawn()} />);
return (
<main class="team">
<section class="team">
{constructPanels}
{spawnButtons}
</main>
</section>
);
}

View File

@ -2,6 +2,17 @@ upstream mnml_dev {
server 0.0.0.0:41337;
}
error_log /var/log/mnml/nginx.log;
upstream mnml_http {
server 127.0.0.1:40000;
}
upstream mnml_ws {
server 127.0.0.1:40055;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
@ -9,25 +20,19 @@ map $http_upgrade $connection_upgrade {
# DEV
server {
root /var/lib/mnml/public/;
index index.html;
server_name dev.mnml.gg; # managed by Certbot
location / {
root /var/lib/mnml/public/current;
index index.html;
try_files $uri $uri/ index.html;
}
location /imgs/ {
root /var/lib/mnml/public/;
try_files $uri $uri/ =404;
}
listen [::]:443;
ssl on;
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/dev.mnml.gg/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/dev.mnml.gg/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location /api/ws {
proxy_pass http://mnml_dev;
proxy_pass http://mnml_ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
@ -35,13 +40,34 @@ server {
}
location /api/ {
proxy_pass http://mnml_dev;
proxy_pass http://mnml_http;
proxy_read_timeout 600s;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mnml.gg/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mnml.gg/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
# http -> https
server {
server_name mnml.gg;
return 301 https://$host$request_uri;
}
server {
server_name minimal.gg;
return 301 https://mnml.gg$request_uri;
}
server {
server_name cryps.gg;
return 301 https://mnml.gg$request_uri;
}
server {
server_name dev.mnml.gg;
return 301 https://$host$request_uri;

View File

@ -1,7 +1,7 @@
use rand::prelude::*;
use rand::{thread_rng};
const FIRSTS: [&'static str; 47] = [
const FIRSTS: [&'static str; 50] = [
"artificial",
"ambient",
"borean",
@ -20,10 +20,13 @@ const FIRSTS: [&'static str; 47] = [
"fierce",
"fossilised",
"frozen",
"gravitational",
"jovian",
"inverted",
"leafy",
"lurking",
"limitless",
"magnetic",
"metallic",
"mossy",
"mighty",
@ -37,6 +40,7 @@ const FIRSTS: [&'static str; 47] = [
"oxygenated",
"oscillating",
"ossified",
"orbiting",
"piscine",
"purified",
"recalcitrant",
@ -46,18 +50,18 @@ const FIRSTS: [&'static str; 47] = [
"supercooled",
"subsonic",
"synthetic",
"sweet",
"terrestrial",
"weary",
];
const LASTS: [&'static str; 52] = [
const LASTS: [&'static str; 55] = [
"artifact",
"assembly",
"carbon",
"console",
"construct",
"craft",
"core",
"design",
"drone",
"distortion",
@ -77,6 +81,8 @@ const LASTS: [&'static str; 52] = [
"lifeform",
"landmass",
"lens",
"mantle",
"magnetism",
"mechanism",
"mountain",
"nectar",