tabbed menu
This commit is contained in:
parent
7af81c5252
commit
a429f21367
@ -10,6 +10,9 @@
|
|||||||
* treats
|
* treats
|
||||||
* constructs jiggle when clicked
|
* constructs jiggle when clicked
|
||||||
* background colour changes depending on time of day
|
* background colour changes depending on time of day
|
||||||
|
* hit animation wobble
|
||||||
|
* combat text scale + translate
|
||||||
|
* susbcriber gold name in instance
|
||||||
|
|
||||||
* bot game grind
|
* bot game grind
|
||||||
* stress test
|
* stress test
|
||||||
|
|||||||
@ -67,6 +67,7 @@ hr {
|
|||||||
color: #222;
|
color: #222;
|
||||||
margin: 1.5em 0;
|
margin: 1.5em 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
border-top: 1px solid #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
@ -287,4 +288,13 @@ header {
|
|||||||
|
|
||||||
nav {
|
nav {
|
||||||
display: none;
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
list-style: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
const { connect } = require('preact-redux');
|
const { connect } = require('preact-redux');
|
||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
|
|
||||||
const Team = require('./team');
|
const Collection = require('./collection');
|
||||||
const Header = require('./header');
|
const Header = require('./header');
|
||||||
const AccountManagement = require('./account.management');
|
const AccountManagement = require('./account.management');
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ function Account(args) {
|
|||||||
return (
|
return (
|
||||||
<main class="menu">
|
<main class="menu">
|
||||||
<Header />
|
<Header />
|
||||||
<Team />
|
|
||||||
<AccountManagement />
|
<AccountManagement />
|
||||||
|
<Collection />
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
89
client/src/components/collection.jsx
Normal file
89
client/src/components/collection.jsx
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
const preact = require('preact');
|
||||||
|
const { connect } = require('preact-redux');
|
||||||
|
|
||||||
|
const actions = require('./../actions');
|
||||||
|
const { COLOURS } = require('./../utils');
|
||||||
|
const { ConstructAvatar } = require('./construct');
|
||||||
|
|
||||||
|
const addState = connect(
|
||||||
|
function receiveState(state) {
|
||||||
|
const { ws, constructs, teamPage, teamSelect } = state;
|
||||||
|
|
||||||
|
function sendConstructSpawn(name) {
|
||||||
|
return ws.sendMtxConstructSpawn(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
constructs,
|
||||||
|
teamPage,
|
||||||
|
teamSelect,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
function receiveDispatch(dispatch) {
|
||||||
|
function setTeam(constructIds) {
|
||||||
|
dispatch(actions.setTeamSelect(constructIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
setTeam,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
function Collection(args) {
|
||||||
|
const {
|
||||||
|
constructs,
|
||||||
|
teamPage,
|
||||||
|
teamSelect,
|
||||||
|
setTeam,
|
||||||
|
} = args;
|
||||||
|
|
||||||
|
if (!constructs) return <div></div>;
|
||||||
|
|
||||||
|
// redux limitation + suggested workaround
|
||||||
|
// so much for dumb components
|
||||||
|
function selectConstruct(id) {
|
||||||
|
// remove
|
||||||
|
const i = teamSelect.findIndex(sid => sid === id);
|
||||||
|
if (i > -1) {
|
||||||
|
teamSelect[i] = null;
|
||||||
|
return setTeam(teamSelect);
|
||||||
|
}
|
||||||
|
|
||||||
|
// window insert
|
||||||
|
const insert = teamSelect.findIndex(j => j === null);
|
||||||
|
if (insert === -1) return setTeam([id, null, null]);
|
||||||
|
teamSelect[insert] = id;
|
||||||
|
return setTeam(teamSelect);
|
||||||
|
}
|
||||||
|
console.log(constructs.length);
|
||||||
|
const dispConstructs = constructs.length >= ((teamPage + 1) * 6)
|
||||||
|
? constructs.slice(teamPage * 6, (teamPage + 1) * 6)
|
||||||
|
: constructs.slice(teamPage * 6, constructs.length);
|
||||||
|
|
||||||
|
const constructPanels = dispConstructs.map(construct => {
|
||||||
|
const colour = teamSelect.indexOf(construct.id);
|
||||||
|
const selected = colour > -1;
|
||||||
|
|
||||||
|
const borderColour = selected ? COLOURS[colour] : '#000000';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={construct.id}
|
||||||
|
class="construct team-select"
|
||||||
|
style={ { 'border-color': borderColour || 'whitesmoke' } }
|
||||||
|
onClick={() => selectConstruct(construct.id)} >
|
||||||
|
<ConstructAvatar construct={construct} />
|
||||||
|
<h2>{construct.name}</h2>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section class="team">
|
||||||
|
{constructPanels}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = addState(Collection);
|
||||||
@ -2,19 +2,13 @@ const { connect } = require('preact-redux');
|
|||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
|
|
||||||
const actions = require('../actions');
|
const actions = require('../actions');
|
||||||
const AccountStatus = require('./account.status');
|
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const {
|
const {
|
||||||
ws,
|
ws,
|
||||||
account,
|
account,
|
||||||
instances,
|
|
||||||
team,
|
|
||||||
nav,
|
nav,
|
||||||
ping,
|
|
||||||
|
|
||||||
game,
|
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
function sendInstanceState(instance) {
|
function sendInstanceState(instance) {
|
||||||
@ -28,11 +22,8 @@ const addState = connect(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
account,
|
account,
|
||||||
instances,
|
|
||||||
team,
|
|
||||||
game,
|
|
||||||
ping,
|
|
||||||
nav,
|
nav,
|
||||||
|
|
||||||
sendInstanceState,
|
sendInstanceState,
|
||||||
sendAccountStates,
|
sendAccountStates,
|
||||||
};
|
};
|
||||||
@ -53,29 +44,19 @@ const addState = connect(
|
|||||||
return dispatch(actions.setNav(place));
|
return dispatch(actions.setNav(place));
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideNav() {
|
|
||||||
return dispatch(actions.setShowNav(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setNav,
|
setNav,
|
||||||
hideNav,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
function Nav(args) {
|
function Header(args) {
|
||||||
const {
|
const {
|
||||||
account,
|
account,
|
||||||
game,
|
|
||||||
team,
|
|
||||||
nav,
|
nav,
|
||||||
|
|
||||||
sendAccountStates,
|
sendAccountStates,
|
||||||
sendInstanceState,
|
|
||||||
|
|
||||||
setNav,
|
setNav,
|
||||||
hideNav,
|
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
if (!account) return false;
|
if (!account) return false;
|
||||||
@ -84,12 +65,6 @@ function Nav(args) {
|
|||||||
return setNav(p);
|
return setNav(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
function joinInstance(i) {
|
|
||||||
sendInstanceState(i);
|
|
||||||
if (game) navTo('transition');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function accountClick() {
|
function accountClick() {
|
||||||
sendAccountStates();
|
sendAccountStates();
|
||||||
navTo('account');
|
navTo('account');
|
||||||
@ -104,8 +79,8 @@ function Nav(args) {
|
|||||||
MNML
|
MNML
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => navTo('news')}
|
onClick={() => navTo('shop')}
|
||||||
class={`login-btn ${nav === 'news' ? 'highlight' : ''}`}>
|
class={`login-btn ${nav === 'shop' ? 'highlight' : ''}`}>
|
||||||
Shop
|
Shop
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@ -118,4 +93,4 @@ function Nav(args) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = addState(Nav);
|
module.exports = addState(Header);
|
||||||
@ -1,100 +0,0 @@
|
|||||||
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 VERSION = process.env.npm_package_version;
|
|
||||||
|
|
||||||
const addState = connect(
|
|
||||||
function receiveState(state) {
|
|
||||||
const {
|
|
||||||
ws,
|
|
||||||
account,
|
|
||||||
shop,
|
|
||||||
} = state;
|
|
||||||
|
|
||||||
function mtxBuy(mtx) {
|
|
||||||
return ws.sendMtxBuy(mtx.variant);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
account,
|
|
||||||
shop,
|
|
||||||
mtxBuy,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
function receiveDispatch(dispatch) {
|
|
||||||
function setMtxActive(mtx) {
|
|
||||||
dispatch(actions.setConstructRename(null));
|
|
||||||
dispatch(actions.setMtxActive(mtx));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
setMtxActive,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function Inventory(args) {
|
|
||||||
const {
|
|
||||||
account,
|
|
||||||
shop,
|
|
||||||
setMtxActive,
|
|
||||||
mtxBuy,
|
|
||||||
} = args;
|
|
||||||
|
|
||||||
if (!shop) return false;
|
|
||||||
|
|
||||||
const useMtx = (item, i) => (
|
|
||||||
<figure key={i} onClick={() => setMtxActive(item)} >
|
|
||||||
<figcaption>{item}</figcaption>
|
|
||||||
<button disabled={account.balance === 0}>¤1</button>
|
|
||||||
</figure>
|
|
||||||
);
|
|
||||||
|
|
||||||
const availableMtx = (item, i) => (
|
|
||||||
<figure key={i} onClick={() => mtxBuy(item)} >
|
|
||||||
<figcaption>{item.variant}</figcaption>
|
|
||||||
<button disabled={account.balance < item.credits}>¤{item.credits}</button>
|
|
||||||
</figure>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class="inventory top">
|
|
||||||
<div class="news">
|
|
||||||
<h1>v{VERSION}</h1>
|
|
||||||
<h2>welcome to mnml</h2>
|
|
||||||
<p>use the buttons on the right to join an instance.</p>
|
|
||||||
<p>
|
|
||||||
select <b>PVP</b> to play against other players.<br />
|
|
||||||
click <b>LEARN</b> to practice the game without time controls.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
if you enjoy the game please support its development by <b>subscribing</b> or purchasing <b>credits</b>.<br />
|
|
||||||
glhf
|
|
||||||
</p>
|
|
||||||
<p>--ntr & mashy</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h1 class="credits">¤ {account.balance}</h1>
|
|
||||||
<Elements>
|
|
||||||
<StripeBtns account={account} />
|
|
||||||
</Elements>
|
|
||||||
<div class='list'>
|
|
||||||
{shop.owned.map(useMtx)}
|
|
||||||
</div>
|
|
||||||
<div class='list'>
|
|
||||||
{shop.available.map(availableMtx)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = addState(Inventory);
|
|
||||||
30
client/src/components/main.bottom.jsx
Normal file
30
client/src/components/main.bottom.jsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
const { connect } = require('preact-redux');
|
||||||
|
const preact = require('preact');
|
||||||
|
|
||||||
|
const actions = require('./../actions');
|
||||||
|
|
||||||
|
const Team = require('./team');
|
||||||
|
const Collection = require('./collection');
|
||||||
|
|
||||||
|
const addState = connect(
|
||||||
|
function receiveState(state) {
|
||||||
|
const {
|
||||||
|
nav,
|
||||||
|
} = state;
|
||||||
|
|
||||||
|
return {
|
||||||
|
nav,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
function Bottom(args) {
|
||||||
|
const {
|
||||||
|
nav,
|
||||||
|
} = args;
|
||||||
|
|
||||||
|
if (nav === 'account') return <Collection />;
|
||||||
|
return <Team />;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = addState(Bottom);
|
||||||
@ -5,14 +5,14 @@ const { connect } = require('preact-redux');
|
|||||||
const Welcome = require('./welcome');
|
const Welcome = require('./welcome');
|
||||||
const Game = require('./game');
|
const Game = require('./game');
|
||||||
const Instance = require('./instance.component');
|
const Instance = require('./instance.component');
|
||||||
const Team = require('./team');
|
const Header = require('./header');
|
||||||
const Play = require('./play');
|
const Top = require('./main.top');
|
||||||
const Account = require('./account.page');
|
const Bottom = require('./main.bottom');
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
state => {
|
state => {
|
||||||
const { game, instance, account, nav, team, constructs } = state;
|
const { game, instance, account, nav } = state;
|
||||||
return { game, instance, account, nav, team, constructs };
|
return { game, instance, account, nav };
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -37,12 +37,13 @@ function Main(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nav === 'transition') return false;
|
if (nav === 'transition') return false;
|
||||||
if (nav === 'play') return <Play />;
|
|
||||||
// if (nav === 'team') return <Team />;
|
|
||||||
if (nav === 'account') return <Account />;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Play />
|
<main class="menu">
|
||||||
|
<Header />
|
||||||
|
<Top />
|
||||||
|
<Bottom />
|
||||||
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
client/src/components/main.top.jsx
Normal file
34
client/src/components/main.top.jsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
const { connect } = require('preact-redux');
|
||||||
|
const preact = require('preact');
|
||||||
|
|
||||||
|
const actions = require('./../actions');
|
||||||
|
|
||||||
|
const AccountTop = require('./account.top');
|
||||||
|
const Play = require('./play');
|
||||||
|
const Shop = require('./shop');
|
||||||
|
|
||||||
|
const addState = connect(
|
||||||
|
function receiveState(state) {
|
||||||
|
const {
|
||||||
|
nav,
|
||||||
|
} = state;
|
||||||
|
|
||||||
|
return {
|
||||||
|
nav,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
function Top(args) {
|
||||||
|
const {
|
||||||
|
nav,
|
||||||
|
} = args;
|
||||||
|
|
||||||
|
if (nav === 'account') return <AccountTop />;
|
||||||
|
if (nav === 'play') return <Play />
|
||||||
|
if (nav === 'shop') return <Shop />
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = addState(Top);
|
||||||
39
client/src/components/menu.jsx
Normal file
39
client/src/components/menu.jsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// eslint-disable-next-line
|
||||||
|
const preact = require('preact');
|
||||||
|
const { connect } = require('preact-redux');
|
||||||
|
|
||||||
|
const Shop = require('./shop');
|
||||||
|
const Play = require('./play');
|
||||||
|
const Account = require('./account.page');
|
||||||
|
|
||||||
|
const addState = connect(
|
||||||
|
state => {
|
||||||
|
const {
|
||||||
|
account,
|
||||||
|
nav,
|
||||||
|
} = state;
|
||||||
|
|
||||||
|
return {
|
||||||
|
account,
|
||||||
|
nav,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
function Menu(props) {
|
||||||
|
const {
|
||||||
|
account,
|
||||||
|
nav,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
// menu
|
||||||
|
if (nav === 'play') return <Play />;
|
||||||
|
if (nav === 'shop') return <Shop />;
|
||||||
|
if (nav === 'account') return <Account />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Play />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = addState(Menu);
|
||||||
31
client/src/components/menu.top.jsx
Normal file
31
client/src/components/menu.top.jsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
const preact = require('preact');
|
||||||
|
const { connect } = require('preact-redux');
|
||||||
|
|
||||||
|
const Shop = require('./shop');
|
||||||
|
const Play = require('./play');
|
||||||
|
const Account = require('./account.page');
|
||||||
|
|
||||||
|
const addState = connect(
|
||||||
|
state => {
|
||||||
|
const { game, instance, account, nav } = state;
|
||||||
|
return { game, instance, account, nav };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
function Menu(props) {
|
||||||
|
const {
|
||||||
|
account,
|
||||||
|
nav,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
// menu
|
||||||
|
if (nav === 'play') return <Play />;
|
||||||
|
if (nav === 'shop') return <Shop />;
|
||||||
|
if (nav === 'account') return <Account />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Play />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = addState(Menu);
|
||||||
@ -1,120 +1,128 @@
|
|||||||
const { connect } = require('preact-redux');
|
// const { connect } = require('preact-redux');
|
||||||
const preact = require('preact');
|
const preact = require('preact');
|
||||||
|
const { connect } = require('preact-redux');
|
||||||
|
const { Elements } = require('react-stripe-elements');
|
||||||
|
|
||||||
const { stringSort } = require('./../utils');
|
|
||||||
const { ConstructAvatar } = require('./construct');
|
|
||||||
const actions = require('./../actions');
|
|
||||||
const Inventory = require('./inventory');
|
|
||||||
const Header = require('./header');
|
const Header = require('./header');
|
||||||
|
const Team = require('./team');
|
||||||
|
const StripeBtns = require('./stripe.buttons');
|
||||||
|
|
||||||
const idSort = stringSort('id');
|
const actions = require('./../actions');
|
||||||
|
|
||||||
|
const VERSION = process.env.npm_package_version;
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const {
|
const {
|
||||||
ws,
|
ws,
|
||||||
constructs,
|
account,
|
||||||
constructRename,
|
shop,
|
||||||
team,
|
|
||||||
mtxActive,
|
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
function sendInstancePractice() {
|
function mtxBuy(mtx) {
|
||||||
return ws.sendInstancePractice();
|
return ws.sendMtxBuy(mtx.variant);
|
||||||
}
|
|
||||||
|
|
||||||
function sendConstructAvatarReroll(id) {
|
|
||||||
console.log('using', mtxActive, 'on', id);
|
|
||||||
return ws.sendMtxApply(id, mtxActive, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendConstructRename(id, name) {
|
|
||||||
ws.sendMtxApply(id, 'Rename', name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
constructs,
|
account,
|
||||||
mtxActive,
|
shop,
|
||||||
constructRename,
|
mtxBuy,
|
||||||
team,
|
|
||||||
sendConstructRename,
|
|
||||||
sendInstancePractice,
|
|
||||||
sendConstructAvatarReroll,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
function receiveDispatch(dispatch) {
|
function receiveDispatch(dispatch) {
|
||||||
function setConstructRename(id) {
|
function setMtxActive(mtx) {
|
||||||
dispatch(actions.setConstructRename(id));
|
dispatch(actions.setConstructRename(null));
|
||||||
|
dispatch(actions.setMtxActive(mtx));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearMtxRename() {
|
function setNav(place) {
|
||||||
dispatch(actions.setConstructRename(null));
|
return dispatch(actions.setNav(place));
|
||||||
dispatch(actions.setMtxActive(null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
clearMtxRename,
|
setMtxActive,
|
||||||
setConstructRename,
|
setNav,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
function Play(args) {
|
function Play(args) {
|
||||||
const {
|
const {
|
||||||
team,
|
account,
|
||||||
constructRename,
|
shop,
|
||||||
clearMtxRename,
|
mtxBuy,
|
||||||
setConstructRename,
|
|
||||||
sendConstructRename,
|
setMtxActive,
|
||||||
mtxActive,
|
setNav,
|
||||||
sendConstructAvatarReroll,
|
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
const constructPanels = team
|
if (!shop) return false;
|
||||||
.map(construct => {
|
|
||||||
const constructName = constructRename === construct.id
|
|
||||||
? <input id='renameInput' type="text" style="text-align: center" placeholder="enter a new name"></input>
|
|
||||||
: <h2>{construct.name}</h2>;
|
|
||||||
|
|
||||||
const confirm = constructRename === construct.id
|
const useMtx = (item, i) => (
|
||||||
? <button onClick={() => sendConstructRename(construct.id, document.getElementById('renameInput').value)}>
|
<figure key={i} onClick={() => setMtxActive(item)} >
|
||||||
Confirm
|
<figcaption>{item}</figcaption>
|
||||||
</button>
|
<button disabled={account.balance === 0}>¤1</button>
|
||||||
: false;
|
</figure>
|
||||||
|
);
|
||||||
|
|
||||||
|
const availableMtx = (item, i) => (
|
||||||
|
<figure key={i} onClick={() => mtxBuy(item)} >
|
||||||
|
<figcaption>{item.variant}</figcaption>
|
||||||
|
<button disabled={account.balance < item.credits}>¤{item.credits}</button>
|
||||||
|
</figure>
|
||||||
|
);
|
||||||
|
|
||||||
|
const subscription = account.subscribed
|
||||||
|
? <button
|
||||||
|
class="stripe-btn"
|
||||||
|
disabled>
|
||||||
|
Subscribed
|
||||||
|
</button>
|
||||||
|
: <button
|
||||||
|
onClick={() => setNav('shop')}
|
||||||
|
class="stripe-btn"
|
||||||
|
role="link">
|
||||||
|
Subscribe
|
||||||
|
</button>;
|
||||||
|
|
||||||
const cancel = constructRename === construct.id
|
|
||||||
? <button onClick={() => clearMtxRename()}>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
: false;
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={construct.id}
|
|
||||||
style={ mtxActive ? { cursor: 'pointer' } : {}}
|
|
||||||
onClick={() => {
|
|
||||||
if (!mtxActive) return false;
|
|
||||||
if (mtxActive === 'Rename') return setConstructRename(construct.id);
|
|
||||||
return sendConstructAvatarReroll(construct.id);
|
|
||||||
}}
|
|
||||||
class="construct">
|
|
||||||
<ConstructAvatar construct={construct} />
|
|
||||||
{constructName}
|
|
||||||
{confirm}
|
|
||||||
{cancel}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main class="menu">
|
<div class="inventory top">
|
||||||
<Header />
|
<div class="news">
|
||||||
<Inventory />
|
<h1>mnml v{VERSION}</h1>
|
||||||
<div class="team">
|
<p>use the buttons on the right to join an instance.</p>
|
||||||
{constructPanels}
|
<p>
|
||||||
|
select <b>PVP</b> to play against other players.<br />
|
||||||
|
click <b>LEARN</b> to practice the game without time controls.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
if you enjoy the game please support its development by <b>subscribing</b> or purchasing <b>credits</b>.<br />
|
||||||
|
glhf
|
||||||
|
</p>
|
||||||
|
<p>--ntr & mashy</p>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
<div>
|
||||||
|
<h1 class="credits">¤ {account.balance}</h1>
|
||||||
|
<div class='list'>
|
||||||
|
{subscription}
|
||||||
|
<button
|
||||||
|
onClick={() => setNav('shop')}
|
||||||
|
class="stripe-btn"
|
||||||
|
role="link">
|
||||||
|
Get Credits
|
||||||
|
</button>
|
||||||
|
<div id="error-message"></div>
|
||||||
|
</div>
|
||||||
|
<div class='list'>
|
||||||
|
{shop.owned.map(useMtx)}
|
||||||
|
</div>
|
||||||
|
<div class='list'>
|
||||||
|
{shop.available.map(availableMtx)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
58
client/src/components/shop.jsx
Normal file
58
client/src/components/shop.jsx
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// const { connect } = require('preact-redux');
|
||||||
|
const preact = require('preact');
|
||||||
|
const { connect } = require('preact-redux');
|
||||||
|
const { Elements } = require('react-stripe-elements');
|
||||||
|
|
||||||
|
const StripeBtns = require('./stripe.buttons');
|
||||||
|
const actions = require('./../actions');
|
||||||
|
|
||||||
|
const addState = connect(
|
||||||
|
function receiveState(state) {
|
||||||
|
const {
|
||||||
|
ws,
|
||||||
|
account,
|
||||||
|
} = state;
|
||||||
|
|
||||||
|
return {
|
||||||
|
account,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
function Shop(args) {
|
||||||
|
const {
|
||||||
|
account,
|
||||||
|
} = args;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="inventory top">
|
||||||
|
<div class="news">
|
||||||
|
<h1>support the game</h1>
|
||||||
|
<p>
|
||||||
|
<b>credits</b> are in game currency that can be used to purchase:
|
||||||
|
<ul>
|
||||||
|
<li>img sets</li>
|
||||||
|
<li>construct renames</li>
|
||||||
|
<li>new constructs</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>subscriptions</b> grant extra benefits:
|
||||||
|
<ul>
|
||||||
|
<li>additional credits</li>
|
||||||
|
<li>chat wheel (soon ™)</li>
|
||||||
|
<li>account icons (soon ™)</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h1 class="credits">¤ {account.balance}</h1>
|
||||||
|
<Elements>
|
||||||
|
<StripeBtns account={account} />
|
||||||
|
</Elements>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = addState(Shop);
|
||||||
@ -6,8 +6,16 @@ function subPlan() {
|
|||||||
return 'prod_FWSA8RoyMMV3st';
|
return 'prod_FWSA8RoyMMV3st';
|
||||||
}
|
}
|
||||||
|
|
||||||
function bitsSku() {
|
function bitsSku(d) {
|
||||||
if (window.location.host === 'mnml.gg') return 'sku_Fjdu7zOy3sLGc5';
|
if (window.location.host === 'mnml.gg') {
|
||||||
|
if (d === 50) return 'sku_Fl5tLCWogUsgus';
|
||||||
|
if (d === 20) return 'sku_Fl5qegnxYRv7Cy';
|
||||||
|
if (d === 10) return 'sku_Fl5qVosoDsUVgy';
|
||||||
|
if (d === 5) return 'sku_Fjdu7zOy3sLGc5';
|
||||||
|
|
||||||
|
// !!!!
|
||||||
|
return 'sku_Fjdu7zOy3sLGc5';
|
||||||
|
}
|
||||||
return 'sku_FjuNxONdWewjH2';
|
return 'sku_FjuNxONdWewjH2';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,6 +24,7 @@ function BitsBtn(args) {
|
|||||||
stripe,
|
stripe,
|
||||||
account,
|
account,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
function subscribeClick() {
|
function subscribeClick() {
|
||||||
stripe.redirectToCheckout({
|
stripe.redirectToCheckout({
|
||||||
items: [{ plan: subPlan(), quantity: 1 }],
|
items: [{ plan: subPlan(), quantity: 1 }],
|
||||||
@ -25,9 +34,9 @@ function BitsBtn(args) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function bitsClick() {
|
function bitsClick(d) {
|
||||||
stripe.redirectToCheckout({
|
stripe.redirectToCheckout({
|
||||||
items: [{ sku: bitsSku(), quantity: 1 }],
|
items: [{ sku: bitsSku(d), quantity: 1 }],
|
||||||
successUrl: window.location.origin,
|
successUrl: window.location.origin,
|
||||||
cancelUrl: window.location.origin,
|
cancelUrl: window.location.origin,
|
||||||
clientReferenceId: account.id,
|
clientReferenceId: account.id,
|
||||||
@ -48,15 +57,29 @@ function BitsBtn(args) {
|
|||||||
</button>;
|
</button>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class='list'>
|
<div>
|
||||||
{subscription}
|
<div class='list'>
|
||||||
<button
|
{subscription}
|
||||||
onClick={bitsClick}
|
</div>
|
||||||
class="stripe-btn"
|
<div class='list'>
|
||||||
role="link">
|
<figure onClick={() => bitsClick(5)} >
|
||||||
Get Credits
|
<figcaption>$5 AUD</figcaption>
|
||||||
</button>
|
<button class="stripe-btn">¤50</button>
|
||||||
<div id="error-message"></div>
|
</figure>
|
||||||
|
<figure onClick={() => bitsClick(10)} >
|
||||||
|
<figcaption>$10 AUD</figcaption>
|
||||||
|
<button class="stripe-btn">¤110</button>
|
||||||
|
</figure>
|
||||||
|
<figure onClick={() => bitsClick(20)} >
|
||||||
|
<figcaption>$20 AUD</figcaption>
|
||||||
|
<button class="stripe-btn">¤250</button>
|
||||||
|
</figure>
|
||||||
|
<figure onClick={() => bitsClick(50)} >
|
||||||
|
<figcaption>$50 AUD</figcaption>
|
||||||
|
<button class="stripe-btn">¤660</button>
|
||||||
|
</figure>
|
||||||
|
<div id="error-message"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,88 +1,112 @@
|
|||||||
const preact = require('preact');
|
|
||||||
const { connect } = require('preact-redux');
|
const { connect } = require('preact-redux');
|
||||||
|
const preact = require('preact');
|
||||||
|
|
||||||
const actions = require('./../actions');
|
|
||||||
const { COLOURS } = require('./../utils');
|
|
||||||
const { ConstructAvatar } = require('./construct');
|
const { ConstructAvatar } = require('./construct');
|
||||||
|
const actions = require('./../actions');
|
||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const { ws, constructs, teamPage, teamSelect } = state;
|
const {
|
||||||
|
ws,
|
||||||
|
constructs,
|
||||||
|
constructRename,
|
||||||
|
team,
|
||||||
|
mtxActive,
|
||||||
|
} = state;
|
||||||
|
|
||||||
function sendConstructSpawn(name) {
|
function sendInstancePractice() {
|
||||||
return ws.sendMtxConstructSpawn(name);
|
return ws.sendInstancePractice();
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendConstructAvatarReroll(id) {
|
||||||
|
console.log('using', mtxActive, 'on', id);
|
||||||
|
return ws.sendMtxApply(id, mtxActive, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendConstructRename(id, name) {
|
||||||
|
ws.sendMtxApply(id, 'Rename', name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
constructs,
|
constructs,
|
||||||
teamPage,
|
mtxActive,
|
||||||
teamSelect,
|
constructRename,
|
||||||
|
team,
|
||||||
|
sendConstructRename,
|
||||||
|
sendInstancePractice,
|
||||||
|
sendConstructAvatarReroll,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
function receiveDispatch(dispatch) {
|
function receiveDispatch(dispatch) {
|
||||||
function setTeam(constructIds) {
|
function setConstructRename(id) {
|
||||||
dispatch(actions.setTeamSelect(constructIds));
|
dispatch(actions.setConstructRename(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearMtxRename() {
|
||||||
|
dispatch(actions.setConstructRename(null));
|
||||||
|
dispatch(actions.setMtxActive(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setTeam,
|
clearMtxRename,
|
||||||
|
setConstructRename,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
function Team(args) {
|
function Team(args) {
|
||||||
const {
|
const {
|
||||||
constructs,
|
team,
|
||||||
teamPage,
|
constructRename,
|
||||||
teamSelect,
|
clearMtxRename,
|
||||||
setTeam,
|
setConstructRename,
|
||||||
|
sendConstructRename,
|
||||||
|
mtxActive,
|
||||||
|
sendConstructAvatarReroll,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
if (!constructs) return <div></div>;
|
const constructPanels = team
|
||||||
|
.map(construct => {
|
||||||
|
const constructName = constructRename === construct.id
|
||||||
|
? <input id='renameInput' type="text" style="text-align: center" placeholder="enter a new name"></input>
|
||||||
|
: <h2>{construct.name}</h2>;
|
||||||
|
|
||||||
// redux limitation + suggested workaround
|
const confirm = constructRename === construct.id
|
||||||
// so much for dumb components
|
? <button onClick={() => sendConstructRename(construct.id, document.getElementById('renameInput').value)}>
|
||||||
function selectConstruct(id) {
|
Confirm
|
||||||
// remove
|
</button>
|
||||||
const i = teamSelect.findIndex(sid => sid === id);
|
: false;
|
||||||
if (i > -1) {
|
|
||||||
teamSelect[i] = null;
|
|
||||||
return setTeam(teamSelect);
|
|
||||||
}
|
|
||||||
|
|
||||||
// window insert
|
const cancel = constructRename === construct.id
|
||||||
const insert = teamSelect.findIndex(j => j === null);
|
? <button onClick={() => clearMtxRename()}>
|
||||||
if (insert === -1) return setTeam([id, null, null]);
|
Cancel
|
||||||
teamSelect[insert] = id;
|
</button>
|
||||||
return setTeam(teamSelect);
|
: false;
|
||||||
}
|
|
||||||
console.log(constructs.length);
|
|
||||||
const dispConstructs = constructs.length >= ((teamPage + 1) * 6)
|
|
||||||
? constructs.slice(teamPage * 6, (teamPage + 1) * 6)
|
|
||||||
: constructs.slice(teamPage * 6, constructs.length);
|
|
||||||
|
|
||||||
const constructPanels = dispConstructs.map(construct => {
|
return (
|
||||||
const colour = teamSelect.indexOf(construct.id);
|
<div
|
||||||
const selected = colour > -1;
|
key={construct.id}
|
||||||
|
style={ mtxActive ? { cursor: 'pointer' } : {}}
|
||||||
const borderColour = selected ? COLOURS[colour] : '#000000';
|
onClick={() => {
|
||||||
|
if (!mtxActive) return false;
|
||||||
return (
|
if (mtxActive === 'Rename') return setConstructRename(construct.id);
|
||||||
<div
|
return sendConstructAvatarReroll(construct.id);
|
||||||
key={construct.id}
|
}}
|
||||||
class="construct team-select"
|
class="construct">
|
||||||
style={ { 'border-color': borderColour || 'whitesmoke' } }
|
<ConstructAvatar construct={construct} />
|
||||||
onClick={() => selectConstruct(construct.id)} >
|
{constructName}
|
||||||
<ConstructAvatar construct={construct} />
|
{confirm}
|
||||||
<h2>{construct.name}</h2>
|
{cancel}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section class="team">
|
<div class="team">
|
||||||
{constructPanels}
|
{constructPanels}
|
||||||
</section>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user