Merge branch 'account' into develop
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
@import 'colours.less';
|
||||
|
||||
.account {
|
||||
margin-top: 2em;
|
||||
grid-area: bottom;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
grid-gap: 0 1em;
|
||||
|
||||
button {
|
||||
display: block;
|
||||
// height: 3em;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
input {
|
||||
width: 75%;
|
||||
height: 3em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.list {
|
||||
letter-spacing: 0.25em;
|
||||
text-transform: uppercase;
|
||||
|
||||
figure {
|
||||
font-size: 125%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#mnml.acp {
|
||||
user-select: text;
|
||||
-moz-user-select: text;
|
||||
-webkit-user-select: text;
|
||||
-ms-user-select: text;
|
||||
|
||||
.bottom {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
.top {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.user {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
@blue: #3050f8;
|
||||
@white: #f5f5f5; // whitesmoke
|
||||
@purple: #9355b5; // 6lack - that far cover
|
||||
@yellow: #ffa100;
|
||||
|
||||
@black: black;
|
||||
@gray: #222;
|
||||
@@ -30,3 +31,33 @@ svg {
|
||||
stroke: @blue;
|
||||
}
|
||||
}
|
||||
|
||||
.green {
|
||||
color: @green;
|
||||
stroke: @green;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: @red;
|
||||
stroke: @red;
|
||||
}
|
||||
|
||||
.red-fill {
|
||||
fill: @red;
|
||||
}
|
||||
|
||||
.blue {
|
||||
color: @blue;
|
||||
stroke: @blue;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
|
||||
.gray {
|
||||
color: #333;
|
||||
stroke: #333;
|
||||
}
|
||||
|
||||
.white {
|
||||
color: @white;
|
||||
stroke: @white;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
aside {
|
||||
grid-area: ctrl;
|
||||
display: grid;
|
||||
|
||||
grid-template-areas:
|
||||
"timer controls"
|
||||
"timer controls"
|
||||
"timer controls";
|
||||
|
||||
grid-template-columns: min-content 1fr;
|
||||
grid-template-rows: 1fr 1fr 1fr;
|
||||
grid-gap: 0.5em 0;
|
||||
|
||||
padding: 1em;
|
||||
padding: 1em 1em 1em 0;
|
||||
|
||||
// fix chrome being inconsistent
|
||||
table {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
div {
|
||||
text-align: right;
|
||||
@@ -28,6 +40,30 @@ aside {
|
||||
border-color: forestgreen;
|
||||
}
|
||||
}
|
||||
|
||||
.timer-container {
|
||||
grid-area: timer;
|
||||
|
||||
display: flex;
|
||||
flex: 1 1 100%;
|
||||
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
|
||||
width: 0.25em;
|
||||
max-width: 0.25em;
|
||||
|
||||
margin: 0 1em 0 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.timer {
|
||||
background: whitesmoke;
|
||||
transition-property: all;
|
||||
transition-duration: 0.25s;
|
||||
transition-delay: 0;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
}
|
||||
|
||||
.ready-btn:hover, .ready-btn:focus, .ready-btn:active {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
footer {
|
||||
display: none;
|
||||
flex-flow: row wrap;
|
||||
grid-area: footer;
|
||||
margin: 0;
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
border: none;
|
||||
background: #222;
|
||||
font-size: 1.5em;
|
||||
padding: 0.25em;
|
||||
|
||||
&[disabled] {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
background: #222;
|
||||
border-right: 1px solid black;
|
||||
}
|
||||
|
||||
.ready {
|
||||
background: forestgreen;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
.timer-container {
|
||||
display: flex;
|
||||
flex: 1 1 100%;
|
||||
width: 100%;
|
||||
height: 0.25em;
|
||||
max-height: 0.25em;
|
||||
|
||||
border: none;
|
||||
margin: 1em 0 0 0;
|
||||
}
|
||||
|
||||
.timer {
|
||||
background: whitesmoke;
|
||||
transition-property: all;
|
||||
transition-duration: 0.25s;
|
||||
transition-delay: 0;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
}
|
||||
|
||||
#nav-btn, #instance-nav {
|
||||
display: none;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
@import 'colours.less';
|
||||
/* GAME */
|
||||
|
||||
.game {
|
||||
@@ -322,15 +323,6 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/*@keyframes rotate {
|
||||
0% {
|
||||
transform: rotateY(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotateY(50deg);
|
||||
}
|
||||
}
|
||||
*/
|
||||
.resolving .skills button {
|
||||
opacity: 0;
|
||||
}
|
||||
@@ -338,80 +330,9 @@
|
||||
.skill-animation {
|
||||
opacity: 0;
|
||||
stroke-width: 5px;
|
||||
height: 5em;
|
||||
}
|
||||
|
||||
/*
|
||||
COMBAT ANIMATIONS
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------
|
||||
* Generated by Animista on 2019-5-21 11:38:30
|
||||
* w: http://animista.net, t: @cssanimista
|
||||
* ---------------------------------------------- */
|
||||
|
||||
|
||||
/*.attack-cast {
|
||||
-webkit-animation: attack-cast 0.5s cubic-bezier(0.550, 0.085, 0.680, 0.530) both;
|
||||
animation: attack-cast 0.5s cubic-bezier(0.550, 0.085, 0.680, 0.530) both;
|
||||
}
|
||||
|
||||
@-webkit-keyframes attack-cast {
|
||||
0% {
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translateY(-5em);
|
||||
transform: translateY(-5em);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes attack-cast {
|
||||
0% {
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translateY(-5em);
|
||||
transform: translateY(-5em);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.attack-hit {
|
||||
-webkit-animation: attack-hit 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
animation: attack-hit 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
}
|
||||
|
||||
@-webkit-keyframes attack-hit {
|
||||
0% {
|
||||
-webkit-transform: translateY(-5em) translateX(5em);
|
||||
transform: translateY(-5em) translateX(5em);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translateY(0) translateX(0);
|
||||
transform: translateY(0) translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes attack-hit {
|
||||
0% {
|
||||
-webkit-transform: translateY(-5em) translateX(5em);
|
||||
transform: translateY(-5em) translateX(5em);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translateY(0) translateX(0);
|
||||
transform: translateY(0) translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@media (max-width: 1000px) {
|
||||
.game {
|
||||
grid-template-areas:
|
||||
|
||||
@@ -426,6 +426,12 @@
|
||||
margin-top: 1em;
|
||||
grid-area: playername;
|
||||
}
|
||||
|
||||
.team {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(min-content, 33%));
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile Nav*/
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
@import 'colours.less';
|
||||
|
||||
.menu {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
|
||||
grid-template-rows: minmax(min-content, 2fr) 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
grid-template-areas:
|
||||
"top"
|
||||
"bottom";
|
||||
|
||||
.top {
|
||||
grid-area: top;
|
||||
padding: 0 0 0.5em 2em;
|
||||
border-bottom: 0.1em solid #222;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
grid-area: bottom;
|
||||
}
|
||||
|
||||
.team {
|
||||
display: grid;
|
||||
grid-area: top;
|
||||
grid-template-columns: repeat(auto-fill, minmax(min-content, 33%));
|
||||
max-height: 100%;
|
||||
|
||||
.team-select:not(:nth-child(3n)) {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.construct {
|
||||
flex: 1 1 33%;
|
||||
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
|
||||
border: 1px solid black;
|
||||
transition-property: border;
|
||||
transition-duration: 0.25s;
|
||||
transition-delay: 0;
|
||||
transition-timing-function: ease;
|
||||
|
||||
button:not(:last-child) {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
pointer-events: none;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.inventory {
|
||||
margin-top: 2em;
|
||||
grid-area: bottom;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
h1 {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.list {
|
||||
letter-spacing: 0.25em;
|
||||
text-transform: uppercase;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 1em;
|
||||
flex-flow: row wrap;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
figure {
|
||||
font-size: 125%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
nav {
|
||||
grid-area: nav;
|
||||
padding-left: 2em;
|
||||
margin-right: 2em;
|
||||
max-height: 100%;
|
||||
|
||||
h1 {
|
||||
margin-bottom: 0.5em;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
h2:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1em 0;
|
||||
border-color: #444;
|
||||
}
|
||||
|
||||
button {
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
color: #888;
|
||||
flex: 1 1 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
button.active {
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
button[disabled], button[disabled]:hover {
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
color: whitesmoke;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
button:focus, button:active {
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
.account-info {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.account-header {
|
||||
letter-spacing: 0.05em;
|
||||
flex: 1;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.account-info svg {
|
||||
margin: 0.5em 0 0 1em;
|
||||
height: 1em;
|
||||
background-color: black;
|
||||
stroke: whitesmoke;
|
||||
}
|
||||
|
||||
.ping-path {
|
||||
fill: none;
|
||||
stroke-width: 4px;
|
||||
stroke-dasharray: 121, 242;
|
||||
animation: saw 2s infinite linear;
|
||||
|
||||
transition-property: stroke-color;
|
||||
transition-duration: 0.25s;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
|
||||
.ping-text {
|
||||
margin-left: 1em;
|
||||
min-width: 3em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.play-btn {
|
||||
font-size: 150%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes saw {
|
||||
0% {
|
||||
stroke-dashoffset: 363;
|
||||
}
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,6 @@
|
||||
@import 'colours.less';
|
||||
|
||||
/*
|
||||
GLOBAL
|
||||
*/
|
||||
|
||||
html, body, #mnml {
|
||||
/*width: 100%;*/
|
||||
margin: 0;
|
||||
|
||||
background-color: black;
|
||||
@@ -48,6 +43,9 @@ html {
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0;
|
||||
margin-bottom: 0.5em;
|
||||
letter-spacing: 0.05em;
|
||||
|
||||
}
|
||||
|
||||
h2 {
|
||||
@@ -66,6 +64,7 @@ h4 {
|
||||
}
|
||||
|
||||
hr {
|
||||
color: #222;
|
||||
margin: 1.5em 0;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -85,70 +84,11 @@ figure {
|
||||
"nav main ctrl";
|
||||
}
|
||||
|
||||
nav {
|
||||
grid-area: nav;
|
||||
padding-left: 2em;
|
||||
margin-right: 2em;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
nav h2:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav h2 {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
nav hr {
|
||||
margin: 1em 0;
|
||||
border-color: #444;
|
||||
}
|
||||
|
||||
nav button {
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
color: #888;
|
||||
flex: 1 1 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
nav button.active {
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
nav button[disabled], nav button[disabled]:hover {
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
nav button:hover {
|
||||
color: whitesmoke;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
nav button:focus, nav button:active {
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 1em;
|
||||
grid-area: main;
|
||||
}
|
||||
|
||||
tr.right:focus, tr.right:hover {
|
||||
box-shadow: inset -0.5em 0 0 0 whitesmoke;
|
||||
}
|
||||
|
||||
tr {
|
||||
transition-property: color, background;
|
||||
transition-duration: 0.25s;
|
||||
transition-delay: 0;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
|
||||
button, input {
|
||||
font-family: 'Jura';
|
||||
color: whitesmoke;
|
||||
@@ -166,22 +106,34 @@ 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 {
|
||||
color: whitesmoke;
|
||||
font-size: 150%;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: whitesmoke;
|
||||
border-color: @gray-hover;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
/*colour necesary to bash skellington*/
|
||||
color: @gray-focus;
|
||||
border-color: @gray-focus;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
svg {
|
||||
@@ -191,19 +143,6 @@ svg {
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
.skill-animation {
|
||||
height: 5em;
|
||||
}
|
||||
|
||||
.team .avatar {
|
||||
object-fit: contain;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
height: auto;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
table {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
@@ -246,64 +185,19 @@ button[disabled] {
|
||||
border-color: #222;
|
||||
}
|
||||
|
||||
/*
|
||||
COLOURS
|
||||
*/
|
||||
|
||||
.green {
|
||||
color: #1FF01F;
|
||||
stroke: #1FF01F;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: #a52a2a;
|
||||
stroke: #a52a2a;
|
||||
}
|
||||
|
||||
.red-fill {
|
||||
fill: #a52a2a;
|
||||
}
|
||||
|
||||
.blue {
|
||||
color: #3050f8;
|
||||
stroke: #3050f8;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
|
||||
.yellow {
|
||||
color: #FFD123;
|
||||
stroke: #FFD123;
|
||||
}
|
||||
|
||||
.purple {
|
||||
color: #A25AC1;
|
||||
stroke: #A25AC1;
|
||||
}
|
||||
|
||||
.cyan {
|
||||
color: #6AD1BF;
|
||||
stroke: #6AD1BF;
|
||||
}
|
||||
|
||||
.gray {
|
||||
color: #333;
|
||||
stroke: #333;
|
||||
}
|
||||
|
||||
.white {
|
||||
color: whitesmoke;
|
||||
stroke: whitesmoke;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
LOGIN
|
||||
*/
|
||||
|
||||
.login {
|
||||
width: 25%;
|
||||
width: 50%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
margin-bottom: 2em;
|
||||
|
||||
h2 {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
#mnml input, #mnml select {
|
||||
@@ -316,242 +210,6 @@ button[disabled] {
|
||||
border-color: #888;
|
||||
}
|
||||
|
||||
/*
|
||||
account
|
||||
*/
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
grid-area: hd;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.account {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
flex: 1;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.account-status {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.account-header {
|
||||
letter-spacing: 0.05em;
|
||||
flex: 1;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.account-status svg {
|
||||
margin: 0.5em 0 0 1em;
|
||||
height: 1em;
|
||||
background-color: black;
|
||||
stroke: whitesmoke;
|
||||
}
|
||||
|
||||
.ping-path {
|
||||
fill: none;
|
||||
stroke-width: 4px;
|
||||
stroke-dasharray: 121, 242;
|
||||
animation: saw 2s infinite linear;
|
||||
|
||||
transition-property: stroke-color;
|
||||
transition-duration: 0.25s;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
|
||||
.ping-text {
|
||||
margin-left: 1em;
|
||||
min-width: 3em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@keyframes saw {
|
||||
0% {
|
||||
stroke-dashoffset: 363;
|
||||
}
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TEAM
|
||||
*/
|
||||
|
||||
.team {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(min-content, 33%));
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.menu-construct {
|
||||
margin: 0.5em;
|
||||
flex: 1 1 auto;
|
||||
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
|
||||
border: 1px solid black;
|
||||
transition-property: border;
|
||||
transition-duration: 0.25s;
|
||||
transition-delay: 0;
|
||||
transition-timing-function: ease;
|
||||
|
||||
button:not(:last-child) {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
pointer-events: none;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.spawn-btn.menu-construct {
|
||||
border: 1px solid #333;
|
||||
color: #333;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.spawn-btn.menu-construct.selected {
|
||||
color: whitesmoke;
|
||||
}
|
||||
|
||||
.spawn-btn.menu-construct:hover {
|
||||
border: 1px solid whitesmoke;
|
||||
}
|
||||
|
||||
.spawn-btn input {
|
||||
flex: 1 1 100%;
|
||||
width: 100%;
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.spawn-btn button {
|
||||
flex: 1 1 100%;
|
||||
margin: 0.5em 1em;
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
.spawn-btn input[disabled], .spawn-btn button[disabled] {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
.play {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
|
||||
grid-template-rows: minmax(min-content, 2fr) 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
grid-template-areas:
|
||||
"team"
|
||||
"inventory";
|
||||
|
||||
.team {
|
||||
grid-area: team;
|
||||
|
||||
/* poor man's <hr>*/
|
||||
padding: 0.5em 2em 0 0;
|
||||
border-bottom: 0.1em solid #444;
|
||||
|
||||
}
|
||||
|
||||
.menu-construct {
|
||||
flex: 1 0 33%;
|
||||
}
|
||||
|
||||
.inventory {
|
||||
margin: 2em 2em 0 0;
|
||||
grid-area: inventory;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
.list {
|
||||
letter-spacing: 0.25em;
|
||||
text-transform: uppercase;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 1em;
|
||||
flex-flow: row wrap;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
figure {
|
||||
font-size: 125%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-instance-btn {
|
||||
flex: 1 1 100%;
|
||||
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%;
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
border: 1px solid #222;
|
||||
float: right;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.create-form {
|
||||
grid-area: create;
|
||||
flex: 1;
|
||||
|
||||
justify-self: flex-end;
|
||||
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.create-form button {
|
||||
flex: 1;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.create-form button:first-child {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.create-form button:hover, .create-form button:focus {
|
||||
border-color: whitesmoke;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
figure.gray {
|
||||
color: #333;
|
||||
stroke-color: #333;
|
||||
@@ -562,56 +220,9 @@ figure.gray {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
main .top button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.timer-container {
|
||||
display: flex;
|
||||
flex: 1 1 100%;
|
||||
width: 100%;
|
||||
height: 0.25em;
|
||||
max-height: 0.25em;
|
||||
|
||||
border: none;
|
||||
margin: 1em 0 0 0;
|
||||
}
|
||||
|
||||
.timer {
|
||||
background: whitesmoke;
|
||||
transition-property: all;
|
||||
transition-duration: 0.25s;
|
||||
transition-delay: 0;
|
||||
transition-timing-function: ease;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: none;
|
||||
flex-flow: row wrap;
|
||||
grid-area: footer;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
footer button {
|
||||
margin: 0;
|
||||
border: none;
|
||||
background: #222;
|
||||
font-size: 1.5em;
|
||||
padding: 0.25em;
|
||||
}
|
||||
|
||||
footer button:disabled {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
footer button:not(:last-child) {
|
||||
background: #222;
|
||||
border-right: 1px solid black;
|
||||
}
|
||||
|
||||
footer button .ready {
|
||||
background: forestgreen;
|
||||
color: black;
|
||||
.credits {
|
||||
color: @yellow;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
@media (max-width: 1500px) {
|
||||
@@ -624,10 +235,6 @@ footer button .ready {
|
||||
}
|
||||
}
|
||||
|
||||
#nav-btn, #instance-nav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-title {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
main {
|
||||
overflow-x: hidden;
|
||||
padding: 0;
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
.login {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>mnml.gg</title>
|
||||
<title>mnml - abstract strategy</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta name=apple-mobile-web-app-capable content=yes>
|
||||
|
||||
+5
-1
@@ -1,8 +1,12 @@
|
||||
require('./assets/styles/styles.less');
|
||||
require('./assets/styles/menu.less');
|
||||
require('./assets/styles/nav.less');
|
||||
require('./assets/styles/footer.less');
|
||||
require('./assets/styles/account.less');
|
||||
require('./assets/styles/controls.less');
|
||||
require('./assets/styles/instance.less');
|
||||
require('./assets/styles/vbox.less');
|
||||
require('./assets/styles/game.less');
|
||||
require('./assets/styles/controls.less');
|
||||
require('./assets/styles/styles.mobile.css');
|
||||
require('./assets/styles/instance.mobile.css');
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"docco": "^0.7.0",
|
||||
"izitoast": "^1.4.0",
|
||||
"keymaster": "^1.6.2",
|
||||
"linkstate": "^1.1.1",
|
||||
"lodash": "^4.17.15",
|
||||
"node-sass": "^4.12.0",
|
||||
"parcel": "^1.12.3",
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
const preact = require('preact');
|
||||
const { Component } = require('preact')
|
||||
const { connect } = require('preact-redux');
|
||||
const linkState = require('linkstate').default;
|
||||
|
||||
const SpawnButton = require('./spawn.button');
|
||||
|
||||
const { postData, errorToast, infoToast } = require('../utils');
|
||||
const actions = require('../actions');
|
||||
|
||||
const addState = connect(
|
||||
function receiveState(state) {
|
||||
const {
|
||||
account,
|
||||
ping,
|
||||
ws,
|
||||
} = state;
|
||||
|
||||
|
||||
function setPassword(current, password) {
|
||||
postData('/account/password', { current, password })
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (!data.success) return errorToast(data.error_message);
|
||||
infoToast('Password changed. Reloading...')
|
||||
setTimeout(() => window.location.reload(), 5000);
|
||||
})
|
||||
.catch(error => errorToast(error));
|
||||
}
|
||||
|
||||
function logout() {
|
||||
postData('/account/logout').then(() => window.location.reload(true));
|
||||
}
|
||||
|
||||
|
||||
function sendConstructSpawn(name) {
|
||||
return ws.sendMtxConstructSpawn(name);
|
||||
}
|
||||
|
||||
return {
|
||||
account,
|
||||
ping,
|
||||
logout,
|
||||
setPassword,
|
||||
sendConstructSpawn,
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
class AccountStatus extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
setPassword: { current: '', password: '', confirm: ''},
|
||||
};
|
||||
}
|
||||
|
||||
render(args) {
|
||||
const {
|
||||
account,
|
||||
ping,
|
||||
logout,
|
||||
setPassword,
|
||||
sendConstructSpawn,
|
||||
} = args;
|
||||
|
||||
if (!account) return null;
|
||||
|
||||
const passwordsEqual = () =>
|
||||
this.state.setPassword.password === this.state.setPassword.confirm;
|
||||
|
||||
const setPasswordDisabled = () => {
|
||||
const { current, password, confirm } = this.state.setPassword;
|
||||
return !(passwordsEqual() && password && current && confirm);
|
||||
}
|
||||
|
||||
return (
|
||||
<section class='account'>
|
||||
<div>
|
||||
<h1>{account.name}</h1>
|
||||
<dl>
|
||||
<dt>Subscription</dt>
|
||||
<dd>{account.subscribed ? 'some date' : 'unsubscribed'}</dd>
|
||||
</dl>
|
||||
<button><a href={`mailto:support@mnml.gg?subject=Account%20Support:%20${account.name}`}>✉ support</a></button>
|
||||
<button onClick={() => logout()}>Logout</button>
|
||||
</div>
|
||||
<div>
|
||||
<label for="email">Email:</label>
|
||||
<dl>
|
||||
<dt>Current Email</dt>
|
||||
<dd>{account.email ? account.email : 'No email set'}</dd>
|
||||
<dt>Status</dt>
|
||||
<dd>{account.email_confirmed ? 'Confirmed' : 'Unconfirmed'}</dd>
|
||||
</dl>
|
||||
<input
|
||||
class="login-input"
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="new email"
|
||||
/>
|
||||
<button>Update</button>
|
||||
</div>
|
||||
<div>
|
||||
<label for="current">Password:</label>
|
||||
<input
|
||||
class="login-input"
|
||||
type="password"
|
||||
name="current"
|
||||
value={this.state.setPassword.current}
|
||||
onInput={linkState(this, 'setPassword.current')}
|
||||
placeholder="current"
|
||||
/>
|
||||
<input
|
||||
class="login-input"
|
||||
type="password"
|
||||
name="new"
|
||||
value={this.state.setPassword.password}
|
||||
onInput={linkState(this, 'setPassword.password')}
|
||||
placeholder="new password"
|
||||
/>
|
||||
<input
|
||||
class="login-input"
|
||||
type="password"
|
||||
name="confirm"
|
||||
value={this.state.setPassword.confirm}
|
||||
onInput={linkState(this, 'setPassword.confirm')}
|
||||
placeholder="confirm"
|
||||
/>
|
||||
<button
|
||||
disabled={setPasswordDisabled()}
|
||||
onClick={() => setPassword(this.state.setPassword.current, this.state.setPassword.password)}>
|
||||
Set Password
|
||||
</button>
|
||||
</div>
|
||||
<div class="list">
|
||||
<figure>
|
||||
<figcaption>spawn new construct</figcaption>
|
||||
<button onClick={() => sendConstructSpawn()} type="submit">
|
||||
¤50
|
||||
</button>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = addState(AccountStatus);
|
||||
@@ -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="menu">
|
||||
<Team />
|
||||
<AccountManagement />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = addState(Account);
|
||||
@@ -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,28 @@ 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() {
|
||||
dispatch(actions.setGame(null));
|
||||
dispatch(actions.setInstance(null));
|
||||
dispatch(actions.setCombiner([]));
|
||||
dispatch(actions.setReclaiming(false));
|
||||
dispatch(actions.setActiveSkill(null));
|
||||
dispatch(actions.setActiveConstruct(null));
|
||||
dispatch(actions.setInfo(null));
|
||||
dispatch(actions.setItemEquip(null));
|
||||
dispatch(actions.setItemUnequip([]));
|
||||
dispatch(actions.setVboxHighlight([]));
|
||||
return dispatch(actions.setNav('account'));
|
||||
}
|
||||
|
||||
return {
|
||||
selectConstructs,
|
||||
accountPage,
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -94,25 +48,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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,12 +10,14 @@ const addState = connect(
|
||||
function receiveState(state) {
|
||||
const {
|
||||
ws,
|
||||
account,
|
||||
game,
|
||||
instance,
|
||||
nav,
|
||||
} = state;
|
||||
|
||||
return {
|
||||
account,
|
||||
game,
|
||||
instance,
|
||||
nav,
|
||||
@@ -26,15 +28,18 @@ const addState = connect(
|
||||
function Controls(args) {
|
||||
const {
|
||||
game,
|
||||
account,
|
||||
instance,
|
||||
nav,
|
||||
sendGameReady,
|
||||
} = args;
|
||||
|
||||
if (!account) return false;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -20,16 +20,22 @@ const addState = connect(
|
||||
return ws.sendGameReady(game.id);
|
||||
}
|
||||
|
||||
function getInstanceState() {
|
||||
return ws.sendInstanceState(game.instance);
|
||||
}
|
||||
|
||||
return {
|
||||
game,
|
||||
sendReady,
|
||||
account,
|
||||
getInstanceState,
|
||||
animating,
|
||||
};
|
||||
},
|
||||
|
||||
function receiveDispatch(dispatch) {
|
||||
function quit() {
|
||||
dispatch(actions.setNav('transition'));
|
||||
dispatch(actions.setGame(null));
|
||||
dispatch(actions.setInstance(null));
|
||||
}
|
||||
@@ -74,6 +80,7 @@ function Controls(args) {
|
||||
animating,
|
||||
sendReady,
|
||||
quit,
|
||||
getInstanceState,
|
||||
} = args;
|
||||
|
||||
if (!game) return false;
|
||||
@@ -81,11 +88,43 @@ function Controls(args) {
|
||||
const opponent = game.players.find(t => t.id !== account.id);
|
||||
const player = game.players.find(t => t.id === account.id);
|
||||
|
||||
function quitClick() {
|
||||
getInstanceState();
|
||||
quit();
|
||||
}
|
||||
|
||||
const zero = Date.parse(game.phase_start);
|
||||
const now = Date.now();
|
||||
const end = Date.parse(game.phase_end);
|
||||
const timerPct = game.phase_end
|
||||
? ((now - zero) / (end - zero) * 100)
|
||||
: 100;
|
||||
|
||||
const displayColour = !game.phase_end
|
||||
? '#222'
|
||||
: player.ready
|
||||
? 'forestgreen'
|
||||
: timerPct > 80
|
||||
? 'red'
|
||||
: 'whitesmoke';
|
||||
|
||||
const timerStyles = {
|
||||
height: `${timerPct > 100 ? 100 : timerPct}%`,
|
||||
background: displayColour,
|
||||
};
|
||||
|
||||
const timer = (
|
||||
<div class="timer-container">
|
||||
<div class="timer" style={timerStyles} > </div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const readyBtn = <button disabled={animating} class="ready" onClick={() => sendReady()}>Ready</button>;
|
||||
const quitBtn = <button disabled={animating} onClick={() => quit()}>Back</button>;
|
||||
const quitBtn = <button disabled={animating} onClick={quitClick}>Back</button>;
|
||||
|
||||
return (
|
||||
<aside class="controls">
|
||||
{timer}
|
||||
{scoreboard(game, opponent, true)}
|
||||
{game.phase === 'Finish' ? quitBtn : readyBtn}
|
||||
{scoreboard(game, player)}
|
||||
|
||||
@@ -66,8 +66,35 @@ function Controls(args) {
|
||||
const opponent = instance.players.find(t => t.id !== account.id);
|
||||
const player = instance.players.find(t => t.id === account.id);
|
||||
|
||||
const zero = Date.parse(instance.phase_start);
|
||||
const now = Date.now();
|
||||
const end = Date.parse(instance.phase_end);
|
||||
const timerPct = instance.phase_end
|
||||
? ((now - zero) / (end - zero) * 100)
|
||||
: 100;
|
||||
|
||||
const displayColour = !instance.phase_end
|
||||
? '#222'
|
||||
: player.ready
|
||||
? 'forestgreen'
|
||||
: timerPct > 80
|
||||
? 'red'
|
||||
: 'whitesmoke';
|
||||
|
||||
const timerStyles = {
|
||||
height: `${timerPct > 100 ? 100 : timerPct}%`,
|
||||
background: displayColour,
|
||||
};
|
||||
|
||||
const timer = (
|
||||
<div class="timer-container">
|
||||
<div class="timer" style={timerStyles} > </div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<aside class="controls">
|
||||
{timer}
|
||||
{scoreboard(instance, opponent, true)}
|
||||
<button class="ready" onClick={() => sendReady()}>Ready</button>
|
||||
{scoreboard(instance, player)}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
const preact = require('preact');
|
||||
const { Component } = require('preact')
|
||||
const { connect } = require('preact-redux');
|
||||
const linkState = require('linkstate').default;
|
||||
|
||||
const { postData, errorToast } = require('../utils');
|
||||
|
||||
@@ -11,10 +12,10 @@ const addState = connect(
|
||||
ws
|
||||
} = state;
|
||||
function submitLogin(name, password) {
|
||||
postData('/login', { name, password })
|
||||
postData('/account/login', { name, password })
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (!data.success) return errorToast(data.error_message);
|
||||
if (data.error) return errorToast(data.error);
|
||||
console.log(data.response);
|
||||
ws.connect();
|
||||
})
|
||||
@@ -22,10 +23,10 @@ const addState = connect(
|
||||
}
|
||||
|
||||
function submitRegister(name, password, code) {
|
||||
postData('/register', { name, password, code })
|
||||
postData('/account/register', { name, password, code })
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (!data.success) return errorToast(data.error_message);
|
||||
if (data.error) return errorToast(data.error);
|
||||
console.log(data.response);
|
||||
ws.connect();
|
||||
})
|
||||
@@ -43,87 +44,122 @@ class Login extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = { name: '', password: '', code: ''};
|
||||
this.state = {
|
||||
login: { name: '', password: '', code: ''},
|
||||
register: { name: '', password: '', confirm: '', code: ''},
|
||||
};
|
||||
|
||||
this.nameInput = this.nameInput.bind(this);
|
||||
this.passwordInput = this.passwordInput.bind(this);
|
||||
this.codeInput = this.codeInput.bind(this);
|
||||
this.loginSubmit = this.loginSubmit.bind(this);
|
||||
this.registerSubmit = this.registerSubmit.bind(this);
|
||||
}
|
||||
|
||||
nameInput(event) {
|
||||
this.setState({ name: event.target.value });
|
||||
}
|
||||
|
||||
passwordInput(event) {
|
||||
this.setState({ password: event.target.value });
|
||||
}
|
||||
|
||||
codeInput(event) {
|
||||
this.setState({ code: event.target.value });
|
||||
}
|
||||
|
||||
loginSubmit(event) {
|
||||
event.preventDefault();
|
||||
console.log(this.state);
|
||||
this.props.submitLogin(this.state.name, this.state.password);
|
||||
this.setState({ name: '', password: '' });
|
||||
this.props.submitLogin(this.state.login.name, this.state.login.password);
|
||||
this.setState({ login: { name: '', password: '' }});
|
||||
}
|
||||
|
||||
registerSubmit(event) {
|
||||
event.preventDefault();
|
||||
this.props.submitRegister(this.state.name, this.state.password, this.state.code);
|
||||
console.log(this.state);
|
||||
this.setState({ name: '', password: '', code: ''});
|
||||
this.props.submitRegister(this.state.register.name, this.state.register.password, this.state.register.code);
|
||||
this.setState({ register: { name: '', password: '', confirm: '', code: ''}});
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const registerConfirm = () =>
|
||||
this.state.register.password === this.state.register.confirm;
|
||||
|
||||
const loginDisabled = () => {
|
||||
const { password, name } = this.state.login;
|
||||
return !(password && name);
|
||||
}
|
||||
|
||||
const registerDisabled = () => {
|
||||
const { password, name, code } = this.state.register;
|
||||
return !(registerConfirm() && password && name && code);
|
||||
}
|
||||
|
||||
return (
|
||||
<main>
|
||||
<h1 class="mobile-title" >mnml.gg</h1>
|
||||
<h1>mnml.gg</h1>
|
||||
<div class="login">
|
||||
<div>mnml is an abstract turn based strategy game</div>
|
||||
<div>free to play</div>
|
||||
<div>no email required</div>
|
||||
</div>
|
||||
<div class="login">
|
||||
<h2>Login</h2>
|
||||
<label for="username">Username</label>
|
||||
<input
|
||||
class="login-input"
|
||||
type="email"
|
||||
placeholder="username"
|
||||
tabIndex={1}
|
||||
value={this.state.name}
|
||||
onInput={this.nameInput}
|
||||
value={this.state.login.name}
|
||||
onInput={linkState(this, 'login.name')}
|
||||
/>
|
||||
<label for="password">Password</label>
|
||||
<input
|
||||
class="login-input"
|
||||
type="password"
|
||||
placeholder="password"
|
||||
tabIndex={2}
|
||||
value={this.state.password}
|
||||
onInput={this.passwordInput}
|
||||
/>
|
||||
<input
|
||||
class="login-input"
|
||||
type="text"
|
||||
placeholder="code"
|
||||
tabIndex={3}
|
||||
value={this.state.code}
|
||||
onInput={this.codeInput}
|
||||
value={this.state.login.password}
|
||||
onInput={linkState(this, 'login.password')}
|
||||
/>
|
||||
<button
|
||||
class="login-btn"
|
||||
tabIndex={4}
|
||||
disabled={loginDisabled()}
|
||||
onClick={this.loginSubmit}>
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
<div class="login">
|
||||
<h2>Register</h2>
|
||||
<label for="username">Username</label>
|
||||
<input
|
||||
class="login-input"
|
||||
type="email"
|
||||
placeholder="username"
|
||||
value={this.state.register.name}
|
||||
onInput={linkState(this, 'register.name')}
|
||||
/>
|
||||
<label for="password">Password - min 12 chars</label>
|
||||
<input
|
||||
class="login-input"
|
||||
type="password"
|
||||
placeholder="password"
|
||||
value={this.state.register.password}
|
||||
onInput={linkState(this, 'register.password')}
|
||||
/>
|
||||
<label for="confirm">Confirm Password</label>
|
||||
<input
|
||||
class={`${registerConfirm() ? '' : 'red'} login-input`}
|
||||
type="password"
|
||||
placeholder="confirm"
|
||||
value={this.state.register.confirm}
|
||||
onInput={linkState(this, 'register.confirm')}
|
||||
/>
|
||||
<label for="code">Access Code</label>
|
||||
<input
|
||||
class="login-input"
|
||||
type="text"
|
||||
placeholder="code"
|
||||
value={this.state.register.code}
|
||||
onInput={linkState(this, 'register.code')}
|
||||
/>
|
||||
<button
|
||||
class="login-btn"
|
||||
tabIndex={5}
|
||||
disabled={registerDisabled()}
|
||||
onClick={this.registerSubmit}>
|
||||
Register
|
||||
</button>
|
||||
<button
|
||||
class="login-btn"
|
||||
onClick={() => document.location.assign('https://discord.gg/YJJgurM')}>
|
||||
Discord + Invites
|
||||
Discord + Codes
|
||||
</button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -69,6 +69,8 @@ function Nav(args) {
|
||||
hideNav,
|
||||
} = args;
|
||||
|
||||
if (!account) return false;
|
||||
|
||||
function navTo(p) {
|
||||
return setNav(p);
|
||||
}
|
||||
@@ -90,6 +92,7 @@ function Nav(args) {
|
||||
|
||||
const canJoin = team.some(c => !c);
|
||||
|
||||
|
||||
return (
|
||||
<nav onClick={hideNav} >
|
||||
<h1 class="header-title">mnml.gg</h1>
|
||||
|
||||
@@ -27,7 +27,8 @@ function JoinButtons(args) {
|
||||
} = args;
|
||||
|
||||
return (
|
||||
<aside>
|
||||
<aside class='play-ctrl'>
|
||||
<div class="timer-container"></div>
|
||||
<button
|
||||
class='pvp ready'
|
||||
onClick={() => sendInstanceQueue()}
|
||||
|
||||
@@ -97,7 +97,7 @@ function Play(args) {
|
||||
if (mtxActive === 'Rename') return setConstructRename(construct.id);
|
||||
return sendConstructAvatarReroll(construct.id);
|
||||
}}
|
||||
class="menu-construct" >
|
||||
class="construct">
|
||||
<ConstructAvatar construct={construct} />
|
||||
{constructName}
|
||||
{confirm}
|
||||
@@ -107,8 +107,8 @@ function Play(args) {
|
||||
});
|
||||
|
||||
return (
|
||||
<main class="play">
|
||||
<div class="team">
|
||||
<main class="menu">
|
||||
<div class="team top">
|
||||
{constructPanels}
|
||||
</div>
|
||||
<Inventory />
|
||||
|
||||
@@ -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);
|
||||
@@ -29,6 +29,7 @@ function TeamCtrl(args) {
|
||||
|
||||
return (
|
||||
<aside>
|
||||
<div class="timer-container"></div>
|
||||
<button
|
||||
class='ready'
|
||||
disabled={teamSelect.some(c => !c)}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
const preact = require('preact');
|
||||
const { connect } = require('preact-redux');
|
||||
const range = require('lodash/range');
|
||||
|
||||
const actions = require('./../actions');
|
||||
const { COLOURS } = require('./../utils');
|
||||
const { stringSort } = require('./../utils');
|
||||
const SpawnButton = require('./spawn.button');
|
||||
const { ConstructAvatar } = require('./construct');
|
||||
|
||||
const addState = connect(
|
||||
@@ -19,7 +16,6 @@ const addState = connect(
|
||||
return {
|
||||
constructs,
|
||||
teamSelect,
|
||||
sendConstructSpawn,
|
||||
};
|
||||
},
|
||||
function receiveDispatch(dispatch) {
|
||||
@@ -31,7 +27,6 @@ const addState = connect(
|
||||
setTeam,
|
||||
};
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
function Team(args) {
|
||||
@@ -39,7 +34,6 @@ function Team(args) {
|
||||
constructs,
|
||||
teamSelect,
|
||||
setTeam,
|
||||
sendConstructSpawn,
|
||||
} = args;
|
||||
|
||||
if (!constructs) return <div></div>;
|
||||
@@ -70,29 +64,19 @@ function Team(args) {
|
||||
return (
|
||||
<div
|
||||
key={construct.id}
|
||||
class="menu-construct"
|
||||
class="construct team-select"
|
||||
style={ { 'border-color': borderColour || 'whitesmoke' } }
|
||||
onClick={() => selectConstruct(construct.id)} >
|
||||
<div class="controls">
|
||||
<h2>
|
||||
{construct.name}
|
||||
</h2>
|
||||
</div>
|
||||
<ConstructAvatar construct={construct} />
|
||||
<h2>{construct.name}</h2>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const spawnButtonsNum = (3 - constructs.length % 3);
|
||||
|
||||
const spawnButtons = range(spawnButtonsNum)
|
||||
.map(i => <SpawnButton key={constructs.length + i} spawn={() => sendConstructSpawn()} />);
|
||||
|
||||
return (
|
||||
<main class="team">
|
||||
<section class="team top">
|
||||
{constructPanels}
|
||||
{spawnButtons}
|
||||
</main>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -213,6 +213,15 @@ function errorToast(message) {
|
||||
});
|
||||
}
|
||||
|
||||
function infoToast(message) {
|
||||
toast.info({
|
||||
position: 'topRight',
|
||||
drag: false,
|
||||
close: false,
|
||||
message,
|
||||
});
|
||||
}
|
||||
|
||||
function convertItem(v) {
|
||||
if (['Red', 'Green', 'Blue'].includes(v)) {
|
||||
return (
|
||||
@@ -233,6 +242,7 @@ module.exports = {
|
||||
postData,
|
||||
convertItem,
|
||||
errorToast,
|
||||
infoToast,
|
||||
NULL_UUID,
|
||||
STATS,
|
||||
COLOURS,
|
||||
|
||||
Reference in New Issue
Block a user