mirror of
https://github.com/chaoticbackup/chaoticbackup.github.io.git
synced 2026-03-21 17:24:14 -05:00
commit
9dea03a02d
|
|
@ -47,6 +47,7 @@
|
|||
}],
|
||||
"keyword-spacing": ["error"],
|
||||
"linebreak-style": "off",
|
||||
"no-console": ["warn", { "allow": [ "info", "warn", "error" ] }],
|
||||
"no-plusplus": "off",
|
||||
"no-prototype-builtins": "off",
|
||||
"no-undef": "error",
|
||||
|
|
@ -75,6 +76,7 @@
|
|||
"react/jsx-indent-props": ["warn", 2],
|
||||
"react/no-unescaped-entities": "off",
|
||||
"react/prop-types": "off",
|
||||
"react-hooks/exhaustive-deps": "warn",
|
||||
"semi": ["warn", "always", { "omitLastInOneLineBlock": true }]
|
||||
},
|
||||
"overrides": [
|
||||
|
|
@ -90,7 +92,7 @@
|
|||
"ecmaFeatures": { "jsx": true },
|
||||
"ecmaVersion": 2019,
|
||||
"sourceType": "module",
|
||||
"project": "./tsconfig.json"
|
||||
"project": ["./tsconfig.json"]
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
1
build/465.js
Normal file
1
build/465.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
"use strict";(self.webpackChunkchaoticbackup=self.webpackChunkchaoticbackup||[]).push([[640],{8640:(e,t,n)=>{n.r(t),n.d(t,{default:()=>u});var a=n(7462),l=n(1721),r=n(7294),o=n(3727),c=n(2195),i=(n(2188),function(){return r.createElement("a",{href:"https://github.com/chaoticbackup",className:"name",rel:"noreferrer noopener",target:"_blank"},"Chaotic Backup Project")}),s=function(e){var t=e.block,n=e.text,a=e.sets;return r.createElement("div",{className:"lore"},r.createElement("div",{className:"block"},t),n.map((function(e,t){return r.createElement("div",{key:t,dangerouslySetInnerHTML:{__html:e}})})),a.map((function(e,t){if(e.text&&e.text.length>0)return r.createElement("div",{className:"set",key:t},r.createElement("div",{className:"title"},e.title),e.text.map((function(e,t){return r.createElement("div",{key:t},e)})))})))},u=function(e){function t(){for(var t,n=arguments.length,a=new Array(n),l=0;l<n;l++)a[l]=arguments[l];return(t=e.call.apply(e,[this].concat(a))||this).state={lore:[]},t}(0,l.Z)(t,e);var n=t.prototype;return n.componentDidMount=function(){var e=this;fetch("/public/json/starter_lore.json").then((function(e){return e.json()})).then((function(t){e.setState({lore:t})})).catch((function(){e.setState({lore:[{block:"Unable to load lore...",text:[]}]})}))},n.render=function(){return r.createElement("div",null,r.createElement("br",null),r.createElement("div",{className:"with-love"},r.createElement("div",null,"Welcome to the ",r.createElement(i,null),"."),r.createElement("span",null,"Built by fans for fans."),r.createElement("br",null),r.createElement("br",null),r.createElement("div",null,"Made with ",r.createElement("span",{className:"heart"},"♥")," by",r.createElement("br",null),"Danude Sandstorm (Project Lead)",r.createElement("br",null),"Chiodosin1 and IvanArial98 (Data Contributions)",r.createElement("br",null),"Blitser, Afjak, and Chiodosin1 (Art and Knowledge)"),r.createElement("div",null,"Do you like the site? You can donate to support it!"),r.createElement("div",{className:"donate"},r.createElement(c.U9,null)),r.createElement("div",{className:"lore"},"We were unsatisfied with the options on how to search for cards. I took the design of the old Chaotic website and added my own modernizations. With an extensive lists of search options in the ",r.createElement(o.rU,{to:"/collection"},"collection"),", you'll find deck building mores streamlined than ever before. Chaotic is full of rich lore, but unfortunately the best database of official lore disapeared when the ",r.createElement(o.rU,{to:"/portal"},"Portal to Perim")," disapeared along with the official site. You can again explore the official lore and information!"),r.createElement("br",null),this.state.lore.length>0?this.state.lore.map((function(e,t){return r.createElement(s,(0,a.Z)({key:t},e))})):"Loading lore entries..."))},t}(r.Component)}}]);
|
||||
"use strict";(self.webpackChunkchaoticbackup=self.webpackChunkchaoticbackup||[]).push([[640],{8640:(e,t,n)=>{n.r(t),n.d(t,{default:()=>u});var a=n(7462),l=n(1721),r=n(7294),o=n(3727),c=n(9637),i=(n(2188),function(){return r.createElement("a",{href:"https://github.com/chaoticbackup",className:"name",rel:"noreferrer noopener",target:"_blank"},"Chaotic Backup Project")}),s=function(e){var t=e.block,n=e.text,a=e.sets;return r.createElement("div",{className:"lore"},r.createElement("div",{className:"block"},t),n.map((function(e,t){return r.createElement("div",{key:t,dangerouslySetInnerHTML:{__html:e}})})),a.map((function(e,t){if(e.text&&e.text.length>0)return r.createElement("div",{className:"set",key:t},r.createElement("div",{className:"title"},e.title),e.text.map((function(e,t){return r.createElement("div",{key:t},e)})))})))},u=function(e){function t(){for(var t,n=arguments.length,a=new Array(n),l=0;l<n;l++)a[l]=arguments[l];return(t=e.call.apply(e,[this].concat(a))||this).state={lore:[]},t}(0,l.Z)(t,e);var n=t.prototype;return n.componentDidMount=function(){var e=this;fetch("/public/json/starter_lore.json").then((function(e){return e.json()})).then((function(t){e.setState({lore:t})})).catch((function(){e.setState({lore:[{block:"Unable to load lore...",text:[]}]})}))},n.render=function(){return r.createElement("div",null,r.createElement("br",null),r.createElement("div",{className:"with-love"},r.createElement("div",null,"Welcome to the ",r.createElement(i,null),"."),r.createElement("span",null,"Built by fans for fans."),r.createElement("br",null),r.createElement("br",null),r.createElement("div",null,"Made with ",r.createElement("span",{className:"heart"},"♥")," by",r.createElement("br",null),"Danude Sandstorm (Project Lead)",r.createElement("br",null),"Chiodosin1 and IvanArial98 (Data Contributions)",r.createElement("br",null),"Blitser, Afjak, and Chiodosin1 (Art and Knowledge)"),r.createElement("div",null,"Do you like the site? You can donate to support it!"),r.createElement("div",{className:"donate"},r.createElement(c.U9,null)),r.createElement("div",{className:"lore"},"We were unsatisfied with the options on how to search for cards. I took the design of the old Chaotic website and added my own modernizations. With an extensive lists of search options in the ",r.createElement(o.rU,{to:"/collection"},"collection"),", you'll find deck building mores streamlined than ever before. Chaotic is full of rich lore, but unfortunately the best database of official lore disapeared when the ",r.createElement(o.rU,{to:"/portal"},"Portal to Perim")," disapeared along with the official site. You can again explore the official lore and information!"),r.createElement("br",null),this.state.lore.length>0?this.state.lore.map((function(e,t){return r.createElement(s,(0,a.Z)({key:t},e))})):"Loading lore entries..."))},t}(r.Component)}}]);
|
||||
1
build/669.css
Normal file
1
build/669.css
Normal file
|
|
@ -0,0 +1 @@
|
|||
.icon14{height:14px;width:14px}.icon14,.icon16{vertical-align:middle}.icon16{height:16px;width:16px}.icon20{height:20px;width:20px}.icon20,.icon24{vertical-align:middle}.icon24{height:24px;width:24px}.name{-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all}.name .subname:before{content:"\a ";white-space:pre}.name .subname{display:inherit;font-size:13px;padding-bottom:4px}.image-cover{background-size:cover;box-sizing:content-box;height:350px;position:absolute;width:250px}.image-cover>div{height:100%;text-align:left;width:100%}.image-cover>div span{color:#000;display:block;font-size:12px;font-weight:700;left:28px;position:relative}.image-cover>div span.long{left:22px}.image-cover>div span:first-of-type{top:222px}.image-cover>div span:nth-of-type(2){top:232px}.image-cover>div span:nth-of-type(3){top:242px}.image-cover>div span:nth-of-type(4){top:252px}.image-cover>div span:nth-of-type(5){font-size:21px;left:-17px;text-align:right;top:260px}.image-cover>div span:nth-of-type(5).long{left:-12px}
|
||||
1
build/669.js
Normal file
1
build/669.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
build/common.js
Normal file
1
build/common.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -33,6 +33,12 @@ and limitations under the License.
|
|||
* @copyright 2014-2019 Yotam Mann
|
||||
*/
|
||||
|
||||
/** @license MUI v5.0.2
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v0.19.1
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
|
|
@ -60,6 +66,15 @@ and limitations under the License.
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v16.14.0
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v16.14.0
|
||||
* react.production.min.js
|
||||
*
|
||||
|
|
@ -77,3 +92,12 @@ and limitations under the License.
|
|||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v17.0.2
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
|
|
|||
22
index.html
22
index.html
|
|
@ -5,25 +5,15 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Chaotic Backup">
|
||||
<link rel="stylesheet" type="text/css" href="/public/css/legacy.css">
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"/>
|
||||
<style>
|
||||
html, body, div, span, a, p, ul, li, h1 {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
/*box-sizing: inherit;*/
|
||||
/* font: inherit;*/
|
||||
/*text-decoration: inherit;*/
|
||||
/*text-align: inherit;*/
|
||||
/*color: inherit;*/
|
||||
/*background: transparent;*/
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
/*pass window height (w/o scroll bars) down to react app, note can't use vh because that includes scroll bars and mobile browser footer, etc so doesn't give viewable area*/
|
||||
html, body { height: 100%; }
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
}
|
||||
html {
|
||||
background-color:#1F1F1F;
|
||||
color: grey;
|
||||
|
|
|
|||
4410
package-lock.json
generated
4410
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
73
package.json
73
package.json
|
|
@ -16,10 +16,11 @@
|
|||
"author": "Danude Sandstorm",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.5.0",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@loadable/component": "^5.15.0",
|
||||
"@material-ui/core": "^4.12.3",
|
||||
"@material-ui/icons": "^4.11.2",
|
||||
"@material-ui/styles": "^4.11.4",
|
||||
"@mui/icons-material": "^5.0.5",
|
||||
"@mui/material": "^5.0.6",
|
||||
"lokijs": "^1.5.12",
|
||||
"mobx": "^5.15.7",
|
||||
"mobx-react": "^6.3.1",
|
||||
|
|
@ -39,57 +40,57 @@
|
|||
"whatwg-fetch": "^3.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.15.7",
|
||||
"@babel/core": "^7.15.5",
|
||||
"@babel/node": "^7.15.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@babel/plugin-proposal-decorators": "^7.15.4",
|
||||
"@babel/plugin-proposal-dynamic-import": "^7.14.5",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.15.6",
|
||||
"@babel/cli": "^7.16.0",
|
||||
"@babel/core": "^7.16.0",
|
||||
"@babel/node": "^7.16.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.16.0",
|
||||
"@babel/plugin-proposal-decorators": "^7.16.0",
|
||||
"@babel/plugin-proposal-dynamic-import": "^7.16.0",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.16.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-computed-properties": "^7.14.5",
|
||||
"@babel/plugin-transform-runtime": "^7.15.0",
|
||||
"@babel/plugin-transform-computed-properties": "^7.16.0",
|
||||
"@babel/plugin-transform-runtime": "^7.16.0",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.15.6",
|
||||
"@babel/preset-react": "^7.14.5",
|
||||
"@babel/preset-typescript": "^7.15.0",
|
||||
"@babel/register": "^7.15.3",
|
||||
"@babel/runtime": "^7.15.4",
|
||||
"@babel/preset-env": "^7.16.0",
|
||||
"@babel/preset-react": "^7.16.0",
|
||||
"@babel/preset-typescript": "^7.16.0",
|
||||
"@babel/register": "^7.16.0",
|
||||
"@babel/runtime": "^7.16.0",
|
||||
"@types/chai": "^4.2.22",
|
||||
"@types/mocha": "^8.2.3",
|
||||
"@types/react": "^16.14.15",
|
||||
"@types/react": "^16.14.20",
|
||||
"@types/react-dom": "^16.9.14",
|
||||
"@types/react-router-dom": "^5.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.31.2",
|
||||
"@typescript-eslint/parser": "^4.31.2",
|
||||
"@types/react-router-dom": "^5.3.2",
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"babel-loader": "^8.2.3",
|
||||
"chai": "^4.3.4",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^6.3.0",
|
||||
"css-minimizer-webpack-plugin": "^3.0.2",
|
||||
"css-loader": "^6.5.1",
|
||||
"css-minimizer-webpack-plugin": "^3.1.1",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-babel": "^5.3.1",
|
||||
"eslint-plugin-import": "^2.24.2",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-react": "^7.26.0",
|
||||
"eslint-plugin-import": "^2.25.2",
|
||||
"eslint-plugin-promise": "^5.1.1",
|
||||
"eslint-plugin-react": "^7.26.1",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"fsevents": "^2.3.2",
|
||||
"ignore-styles": "^5.0.1",
|
||||
"jsdom": "^17.0.0",
|
||||
"jsdom-global": "^3.0.2",
|
||||
"mini-css-extract-plugin": "^2.3.0",
|
||||
"mini-css-extract-plugin": "^2.4.4",
|
||||
"mocha": "^8.4.0",
|
||||
"postcss": "^8.3.7",
|
||||
"sass": "^1.42.1",
|
||||
"sass-loader": "^12.1.0",
|
||||
"style-loader": "^3.3.0",
|
||||
"postcss": "^8.3.11",
|
||||
"sass": "^1.43.4",
|
||||
"sass-loader": "^12.3.0",
|
||||
"style-loader": "^3.3.1",
|
||||
"terser-webpack-plugin": "^5.2.4",
|
||||
"ts-node": "^10.2.1",
|
||||
"typescript": "^4.4.3",
|
||||
"webpack": "^5.53.0",
|
||||
"webpack-cli": "^4.8.0",
|
||||
"ts-node": "^10.4.0",
|
||||
"typescript": "^4.4.4",
|
||||
"webpack": "^5.61.0",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
},
|
||||
"browser": {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,20 @@
|
|||
html, body, div, span, a, p, ul, li, h1 {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
/*box-sizing: inherit;*/
|
||||
/* font: inherit;*/
|
||||
/*text-decoration: inherit;*/
|
||||
/*text-align: inherit;*/
|
||||
/*color: inherit;*/
|
||||
/*background: transparent;*/
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 975px) {
|
||||
.legacy.content {
|
||||
margin-top: 36px;
|
||||
|
|
|
|||
128
src/components/BaseStylesWrapper.js
Normal file
128
src/components/BaseStylesWrapper.js
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import API from './SpreadsheetData';
|
||||
import { Donate } from './Snippets';
|
||||
|
||||
export default function Base({ children }) {
|
||||
// Configuration for the language and background
|
||||
// Images managed in css file
|
||||
const language = "ENG";
|
||||
const bkgrnd = "05";
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="fix-pgBkgrnd-repeat-x">
|
||||
<div className={"fix-img-bkgrnd fix-img-bkgrnd_"+bkgrnd}></div>
|
||||
</div>
|
||||
<div className="pgBkgrnd-repeat-x">
|
||||
<div className="img-bkgrnd">
|
||||
<div className="content-wrap">
|
||||
<div className="legacy legacy-header">
|
||||
<div className="header">
|
||||
<div id="nav">
|
||||
<div className="zero-clear-line headerSpriteNav-wrap">
|
||||
<ul id="unity-sprite" className={language}>
|
||||
<li id="unity-nav1" className={language}></li>
|
||||
<li id="unity-nav2" className={language}><Link to={`/collection/`}><span>Collect</span></Link></li>
|
||||
<li id="unity-nav3" className={language}><a href="https://chaoticbackup.forumotion.com/f11-deck-building"><span>Build</span></a></li>
|
||||
<li id="unity-nav4" className={language}><a href="https://chaoticbackup.forumotion.com/f16-trading-buying-and-selling"><span>Trade</span></a></li>
|
||||
<li id="unity-nav5" className={language}><Link to={`/`}><span>Home</span></Link></li>
|
||||
<li id="unity-nav6" className={language}><a href="https://chaoticbackup.forumotion.com"><span>Forums</span></a></li>
|
||||
<li id="unity-nav7" className={language}><Link to={`/portal/`}><span>Portal</span></Link></li>
|
||||
<li id="unity-nav8" className={language}><a href="https://chaoticrecode.com"><span>Play</span></a></li>
|
||||
<li id="unity-nav9" className={language}></li>
|
||||
</ul>
|
||||
<ul id="unityETC-sprite" className={language}>
|
||||
<li id="unity-nav10" className={language}><Link to={`/EnterTheCode`}><span>Enter the Code</span></Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="banner-ad-top">
|
||||
</div>
|
||||
<div className="legacy content">
|
||||
<div className="left-column">
|
||||
<div className="full-width clear-line" style={{ marginBottom: "5px" }}>
|
||||
</div>
|
||||
</div>
|
||||
<div className="full-column">
|
||||
<div className="pods-wrap pad5px-btm">
|
||||
<div className="clear-line full-width">
|
||||
<div className="adPod-top-wrap">
|
||||
<div className="videoAdPod-topleft">
|
||||
<div className="videoAdPod-topLeft-repeat-x"></div>
|
||||
</div>
|
||||
<div className="videoAdPod-topright">
|
||||
<div className="videoAdPod-topRight-repeat-x"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-area-repeat-xy">
|
||||
<div className="content-area-top-repeat-x">
|
||||
<div className="content-area-left-repeat-y">
|
||||
<div className="content-area-right-repeat-y">
|
||||
<div className="content-area-inner-space">
|
||||
<div id="player">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-btm-wrap">
|
||||
<div className="content-area-btm-left">
|
||||
<div className="content-left-btm-repeat-x">
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-area-btm-right">
|
||||
<div className="content-right-btm-repeat-x">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="right-column">
|
||||
<div className="full-width clear-line" style={{ marginBottom: "5px" }}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="banner-ad-bottom">
|
||||
</div>
|
||||
<div className="legacy legacy-footer">
|
||||
<div className="footer-wrap">
|
||||
<div className="footer-repeat-x">
|
||||
<div className="footer-left">
|
||||
<div className="footer-right">
|
||||
<div className="footer-text">
|
||||
<div className="footer-search">
|
||||
<br /><br />
|
||||
<Donate />
|
||||
</div>
|
||||
<div className="footer-nav">
|
||||
<div className="copyright">
|
||||
©2008 Chaotic USA Entertainment Group, Inc.
|
||||
<br />
|
||||
U.S. Pat 5810666 and 5954332 and other pending patent applications. All Rights Reserved.
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer-language">
|
||||
<a href='#' onClick={(e) => {e.stopPropagation(); e.preventDefault(); API.purgeDB()}} className="page-options" title="Change Language">
|
||||
<img src="/public/img/flag_usa_.gif" alt="English (Change Language)" width="40" height="27"/>
|
||||
<br />English (Change Language)
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
import React from 'react';
|
||||
import processString from 'react-process-string';
|
||||
import { Mugic, Element, Discipline, Tribe } from "./_text";
|
||||
|
||||
export function Ability(props) {
|
||||
const mugic_counters = {
|
||||
regex: /([0-9x]*){{mc}}/i,
|
||||
fn: (key, result) => {
|
||||
if (result.length > 1 && result[1] != "") {
|
||||
return (<Mugic key={key} tribe={props.tribe} amount={result[1].toLowerCase()} size="icon14" />);
|
||||
}
|
||||
return (<Mugic key={key} tribe={props.tribe} size="icon14" />);
|
||||
}
|
||||
};
|
||||
|
||||
const elements = {
|
||||
regex: new RegExp(/(\b((fire)|(air)|(earth)|(water)))/i),
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><Element element={result[0].replace(/\b/, '')} value="true" size="icon14" />{result[0]}</span>);
|
||||
}
|
||||
};
|
||||
|
||||
const disciplines = {
|
||||
regex: /(courage)|(power)|(wisdom)|(speed)/i,
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><Discipline discipline={result[0]} size="icon14" />{result[0]}</span>);
|
||||
}
|
||||
};
|
||||
|
||||
const tribes = {
|
||||
regex: /(danian)|(generic)|(mipedian)|(overworld)|(underworld)|(m'arrillian)/i,
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><Tribe tribe={result[0]} size="icon14" />{result[0]}</span>);
|
||||
}
|
||||
};
|
||||
|
||||
const filters = [mugic_counters, elements, disciplines, tribes];
|
||||
|
||||
return <div className={props.type || "ability"}>{processString(filters)(props.ability)}</div>;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
import React from 'react';
|
||||
|
||||
export function Initiative(props) {
|
||||
const { initiative } = props;
|
||||
let image = null;
|
||||
if (["Danian", "Generic", "Mipedian", "OverWorld", "UnderWorld", "M'arrillian"].indexOf(initiative) > -1) {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/public/img/icons/tribes/" + initiative + ".png").toLowerCase()} />;
|
||||
}
|
||||
else if (["courage", "power", "speed", "wisdom"].indexOf(initiative.toLowerCase()) > -1) {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/public/img/icons/disciplines/" + initiative + ".png").toLowerCase()} />;
|
||||
}
|
||||
else if (["fire", "air", "earth", "water"].indexOf(initiative.toLowerCase()) > -1) {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/public/img/icons/elements/" + initiative + ".png").toLowerCase()} />;
|
||||
}
|
||||
else if (initiative.toLowerCase() == "mugic counter") {
|
||||
image = <img className="icon16" style={{ verticalAlign: 'middle' }} src={("/public/img/icons/mugic/generic.png").toLowerCase()} />;
|
||||
}
|
||||
return (<span>{!props.notitle && ("Initiative: ")}{image} {initiative}</span>);
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import React from 'react';
|
||||
import API from '../SpreadsheetData';
|
||||
|
||||
export function AttackIcon(props) {
|
||||
const attack = "attack" + ((props.bp && props.bp >= 0) ? "_" + props.bp : "");
|
||||
|
|
@ -14,12 +13,51 @@ export function LocationIcon(props) {
|
|||
return <img className={props.size || "icon16"} src="/public/img/icons/location.png" />;
|
||||
}
|
||||
|
||||
export function Rarity(props) {
|
||||
const { set, rarity, iconOnly=false } = props;
|
||||
return (
|
||||
<span>
|
||||
{set !== 'PE1' && <img className={props.size || "icon16"} style={{ verticalAlign: 'middle' }} src={("/public/img/icons/set/" + set + "/" + rarity + ".png").toLowerCase()} />}
|
||||
{!iconOnly && <>{API.sets[props.set]} | {props.rarity}</>}
|
||||
</span>
|
||||
);
|
||||
export function RarityIcon(props) {
|
||||
const { set, rarity, size } = props;
|
||||
return (<>{set !== 'PE1' &&
|
||||
<img className={size || "icon16"} style={{ verticalAlign: 'middle' }} src={("/public/img/icons/set/" + set + "/" + rarity + ".png").toLowerCase()} />
|
||||
}</>);
|
||||
}
|
||||
|
||||
export function MugicIcon(props) {
|
||||
const type = (props.tribe || "generic") + (props.amount != undefined ? `_${props.amount}` : "");
|
||||
const src = ("/public/img/icons/mugic/" + type + ".png").toLowerCase();
|
||||
return <img className={props.size || "icon20"} src={src} alt={"MC"} />;
|
||||
}
|
||||
|
||||
export function ElementIcon(props) {
|
||||
if (props.value) {
|
||||
return <img className={props.size || "icon20"} src={("/public/img/icons/elements/" + props.element + ".png").toLowerCase()} />;
|
||||
}
|
||||
else {
|
||||
return <img className={props.size || "icon20"} src={("/public/img/icons/elements/" + props.element + "-inactive.png").toLowerCase()} />;
|
||||
}
|
||||
}
|
||||
|
||||
export function TribeIcon(props) {
|
||||
return <img className={props.size || "icon16"} src={("/public/img/icons/tribes/" + props.tribe + ".png").toLowerCase()} />;
|
||||
}
|
||||
|
||||
export function DisciplineIcon(props) {
|
||||
return <img className={props.size || "icon16"} src={("/public/img/icons/disciplines/" + props.discipline + ".png").toLowerCase()} />;
|
||||
}
|
||||
|
||||
export function InitiativeIcon(props) {
|
||||
const { initiative } = props;
|
||||
let image = <></>;
|
||||
if (["Danian", "Generic", "Mipedian", "OverWorld", "UnderWorld", "M'arrillian"].indexOf(initiative) > -1) {
|
||||
image = <img className={props.size || "icon16"} style={{ verticalAlign: 'middle' }} src={("/public/img/icons/tribes/" + initiative + ".png").toLowerCase()} />;
|
||||
}
|
||||
else if (["courage", "power", "speed", "wisdom"].indexOf(initiative.toLowerCase()) > -1) {
|
||||
image = <img className={props.size || "icon16"} style={{ verticalAlign: 'middle' }} src={("/public/img/icons/disciplines/" + initiative + ".png").toLowerCase()} />;
|
||||
}
|
||||
else if (["fire", "air", "earth", "water"].indexOf(initiative.toLowerCase()) > -1) {
|
||||
image = <img className={props.size || "icon16"} style={{ verticalAlign: 'middle' }} src={("/public/img/icons/elements/" + initiative + ".png").toLowerCase()} />;
|
||||
}
|
||||
else if (initiative.toLowerCase() == "mugic counter") {
|
||||
image = <img className={props.size || "icon16"} style={{ verticalAlign: 'middle' }} src={("/public/img/icons/mugic/generic.png").toLowerCase()} />;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
import React from 'react';
|
||||
import API from '../SpreadsheetData';
|
||||
import { abilityText } from './abilityText';
|
||||
import { uniqueText } from './uniqueText';
|
||||
import { InitiativeIcon, RarityIcon } from './_icons';
|
||||
|
||||
export function Name(props) {
|
||||
const name = props.name.split(",");
|
||||
|
|
@ -15,29 +19,37 @@ export function Name(props) {
|
|||
</div>);
|
||||
}
|
||||
|
||||
export function Mugic(props) {
|
||||
const type = (props.tribe || "generic") + (props.amount != undefined ? `_${props.amount}` : "");
|
||||
const src = ("/public/img/icons/mugic/" + type + ".png").toLowerCase();
|
||||
return <img className={props.size || "icon20"} src={src} alt={"MC"} />;
|
||||
}
|
||||
|
||||
export function Element(props) {
|
||||
if (props.value) {
|
||||
return <img className={props.size || "icon20"} src={("/public/img/icons/elements/" + props.element + ".png").toLowerCase()} />;
|
||||
}
|
||||
else {
|
||||
return <img className={props.size || "icon20"} src={("/public/img/icons/elements/" + props.element + "-inactive.png").toLowerCase()} />;
|
||||
}
|
||||
}
|
||||
|
||||
export function Tribe(props) {
|
||||
return <img className={props.size || "icon16"} src={("/public/img/icons/tribes/" + props.tribe + ".png").toLowerCase()} />;
|
||||
}
|
||||
|
||||
export function Discipline(props) {
|
||||
return <img className={props.size || "icon16"} src={("/public/img/icons/disciplines/" + props.discipline + ".png").toLowerCase()} />;
|
||||
export function Rarity(props) {
|
||||
const { set, rarity, id = -1 } = props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<RarityIcon {...props} />
|
||||
{(id === -1)
|
||||
? (<>{API.sets[props.set]} | {props.rarity}</>)
|
||||
: (<>{` ${API.sets[set]} `}<span style={{ fontWeight: 'bold' }}>{`# ${id}`}</span>{` | ${rarity}`}</>)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function FlavorText({ flavortext }) {
|
||||
return (flavortext) ? <div className="flavortext">{flavortext}</div> : <></>;
|
||||
}
|
||||
|
||||
export function Ability(props) {
|
||||
return <div className={props.type || "ability"}>{abilityText(props)}</div>;
|
||||
}
|
||||
|
||||
export function Unique(props) {
|
||||
const string = uniqueText(props);
|
||||
|
||||
if (string === "") return <></>;
|
||||
else return (
|
||||
<div style={{ fontWeight: "Bold" }}>{string}</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Initiative(props) {
|
||||
return (<span>{!props.notitle && ("Initiative: ")}{InitiativeIcon(props)} {props.initiative}</span>);
|
||||
}
|
||||
|
|
|
|||
42
src/components/Snippets/abilityText.js
Normal file
42
src/components/Snippets/abilityText.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import React from 'react';
|
||||
import processString from 'react-process-string';
|
||||
import { MugicIcon, ElementIcon, DisciplineIcon, TribeIcon } from "./_icons";
|
||||
|
||||
export function abilityText(props) {
|
||||
if (!props.ability || props.ability.length === 0) return "";
|
||||
|
||||
const mugic_counters = {
|
||||
regex: /([0-9x]*){{mc}}/i,
|
||||
fn: (key, result) => {
|
||||
if (result.length > 1 && result[1] != "") {
|
||||
return (<MugicIcon key={key} tribe={props.tribe} amount={result[1].toLowerCase()} size={props.size || "icon14"} />);
|
||||
}
|
||||
return (<MugicIcon key={key} tribe={props.tribe} size={props.size || "icon14"} />);
|
||||
}
|
||||
};
|
||||
|
||||
const elements = {
|
||||
regex: new RegExp(/(\b((fire)|(air)|(earth)|(water))\b)/i),
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><ElementIcon element={result[0].replace(/\b/, '')} value="true" size={props.size || "icon14"} />{result[0]}</span>);
|
||||
}
|
||||
};
|
||||
|
||||
const disciplines = {
|
||||
regex: /(courage)|(power)|(wisdom)|(speed)/i,
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><DisciplineIcon discipline={result[0]} size={props.size || "icon14"} />{result[0]}</span>);
|
||||
}
|
||||
};
|
||||
|
||||
const tribes = {
|
||||
regex: /(danian)|(generic)|(mipedian)|(overworld)|(underworld)|(m'arrillian)/i,
|
||||
fn: (key, result) => {
|
||||
return (<span key={key}><TribeIcon tribe={result[0]} size={props.size || "icon14"} />{result[0]}</span>);
|
||||
}
|
||||
};
|
||||
|
||||
const filters = [mugic_counters, elements, disciplines, tribes];
|
||||
|
||||
return processString(filters)(props.ability);
|
||||
}
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
import React from 'react';
|
||||
import s from '../../styles/app.style';
|
||||
|
||||
export { Unique } from './Unique';
|
||||
export { Initiative } from './Initiative';
|
||||
export { Ability } from './Ability';
|
||||
export * from './_icons';
|
||||
export * from './_text';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import React from 'react';
|
||||
|
||||
export function Unique(props) {
|
||||
export function uniqueText(props) {
|
||||
let string = "";
|
||||
if (props.data.unique) {
|
||||
string += "Unique, ";
|
||||
|
|
@ -20,8 +18,5 @@ export function Unique(props) {
|
|||
}
|
||||
string = string.replace(/,\s+$/, "");
|
||||
|
||||
if (string === "") return <></>;
|
||||
else return (
|
||||
<div style={{ fontWeight: "Bold" }}>{string}</div>
|
||||
);
|
||||
return string;
|
||||
}
|
||||
|
|
@ -17,6 +17,27 @@ function retry (fn: () => any, retries=0, err=null) {
|
|||
});
|
||||
}
|
||||
|
||||
// For the conversion of shorthand in database
|
||||
export const sets = {
|
||||
"DOP": "Dawn of Perim",
|
||||
"ZOTH": "Zenith of the Hive",
|
||||
"SS": "Silent Sands",
|
||||
"MI": "Beyond the Doors",
|
||||
"ROTO": "Rise of the Oligarch",
|
||||
"TOTT": "Turn of the Tide",
|
||||
"FUN": "Forged Unity",
|
||||
"AU": "Alliance Unraveled",
|
||||
"FAS": "Fire and Stone",
|
||||
"OP1": "Organized Play 1",
|
||||
"PE1": "Premium Edition 1",
|
||||
"SAS": "Storm and Sea",
|
||||
"EE": "Elemental Emperors",
|
||||
"BR": "Beyond Rare",
|
||||
"LR": "League Rewards",
|
||||
"PROMO": "Promotional",
|
||||
"PROTO": "Prototype"
|
||||
};
|
||||
|
||||
class API {
|
||||
@observable portal;
|
||||
@observable cards;
|
||||
|
|
@ -173,27 +194,8 @@ class API {
|
|||
return ["Danian", "Generic", "Mipedian", "M'arrillian", "OverWorld", "UnderWorld"];
|
||||
}
|
||||
|
||||
// For the conversion of shorthand in database
|
||||
get sets() {
|
||||
return {
|
||||
"DOP": "Dawn of Perim",
|
||||
"ZOTH": "Zenith of the Hive",
|
||||
"SS": "Silent Sands",
|
||||
"MI": "Beyond the Doors",
|
||||
"ROTO": "Rise of the Oligarch",
|
||||
"TOTT": "Turn of the Tide",
|
||||
"FUN": "Forged Unity",
|
||||
"AU": "Alliance Unraveled",
|
||||
"FAS": "Fire and Stone",
|
||||
"OP1": "Organized Play 1",
|
||||
"PE1": "Premium Edition 1",
|
||||
"SAS": "Storm and Sea",
|
||||
"EE": "Elemental Emperors",
|
||||
"BR": "Beyond Rare",
|
||||
"LR": "League Rewards",
|
||||
"PROMO": "Promotional",
|
||||
"PROTO": "Prototype"
|
||||
};
|
||||
return sets;
|
||||
}
|
||||
|
||||
purgeDB() {
|
||||
|
|
@ -206,4 +208,4 @@ class API {
|
|||
|
||||
}
|
||||
|
||||
export default API;
|
||||
export default API.getInstance();
|
||||
|
|
|
|||
3
src/components/SpreadsheetData/index.js
Normal file
3
src/components/SpreadsheetData/index.js
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import API from './API';
|
||||
|
||||
export default API;
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import API from './API';
|
||||
|
||||
export default API.getInstance();
|
||||
19
src/components/_hooks/useCheckMobileScreen.js
Normal file
19
src/components/_hooks/useCheckMobileScreen.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
|
||||
const useCheckMobileScreen = () => {
|
||||
const [width, setWidth] = useState(window.innerWidth);
|
||||
const handleWindowSizeChange = () => {
|
||||
setWidth(window.innerWidth);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('resize', handleWindowSizeChange);
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleWindowSizeChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (width < 975);
|
||||
};
|
||||
|
||||
export default useCheckMobileScreen;
|
||||
47
src/components/_mobile/collection/Attack.tsx
Normal file
47
src/components/_mobile/collection/Attack.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import { Typography } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { Attack } from "../../common/definitions";
|
||||
import { AttackIcon, ElementIcon, Name } from '../../Snippets';
|
||||
import { abilityText } from '../../Snippets/abilityText';
|
||||
import { uniqueText } from '../../Snippets/uniqueText';
|
||||
import { CardBase, CardComponent, Flavor, Unique, Rarity } from './CardBase';
|
||||
|
||||
const AttackCard: CardBase<Attack> = (props) => {
|
||||
const { card } = props;
|
||||
|
||||
const ability = abilityText({ ability: card.gsx$ability, size: "icon16" });
|
||||
const unique = uniqueText({ data: { unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }});
|
||||
const flavor = card.gsx$flavortext;
|
||||
|
||||
return (
|
||||
<CardComponent {...props}
|
||||
right={<>
|
||||
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
|
||||
{unique && <Unique>{unique}</Unique>}
|
||||
{flavor && <Flavor>{flavor}</Flavor>}
|
||||
</>}
|
||||
left={<>
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity {...props} />
|
||||
<Typography><AttackIcon size="icon20" bp={card.gsx$bp} /> Attack - {card.gsx$bp}</Typography>
|
||||
<Typography>
|
||||
{`${card.gsx$base} | `}
|
||||
<ElementIcon element="fire" value={card.gsx$fire} />{`${card.gsx$fire} `}
|
||||
<ElementIcon element="air" value={card.gsx$air} />{`${card.gsx$air} `}
|
||||
<ElementIcon element="earth" value={card.gsx$earth} />{`${card.gsx$earth} `}
|
||||
<ElementIcon element="water" value={card.gsx$water} />{`${card.gsx$water}`}
|
||||
</Typography>
|
||||
</>}
|
||||
content={<>
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity {...props} />
|
||||
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
|
||||
{unique && <Unique>{unique}</Unique>}
|
||||
{flavor && <Flavor>{flavor}</Flavor>}
|
||||
<Typography>Art By: {card.gsx$artist}</Typography>
|
||||
</>}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default AttackCard;
|
||||
39
src/components/_mobile/collection/Battlegear.tsx
Normal file
39
src/components/_mobile/collection/Battlegear.tsx
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import { Typography } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { BattlegearIcon, Name } from '../../Snippets';
|
||||
import { Battlegear } from '../../common/definitions';
|
||||
import { abilityText } from '../../Snippets/abilityText';
|
||||
import { uniqueText } from '../../Snippets/uniqueText';
|
||||
import { CardBase, CardComponent, Unique, Flavor, Rarity } from './CardBase';
|
||||
|
||||
const BattlegearCard: CardBase<Battlegear> = (props) => {
|
||||
const { card } = props;
|
||||
const ability = abilityText({ ability: card.gsx$ability, size: "icon16" });
|
||||
const unique = uniqueText({ data: { unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }});
|
||||
const flavor = card.gsx$flavortext;
|
||||
|
||||
return (
|
||||
<CardComponent {...props}
|
||||
left={<>
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity {...props} />
|
||||
<Typography><BattlegearIcon size="icon20"/> Battlegear{card.gsx$types.length > 0 ? ` - ${card.gsx$types}` : null}</Typography>
|
||||
</>}
|
||||
right={<>
|
||||
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
|
||||
{unique && <Unique>{unique}</Unique>}
|
||||
{flavor && <Flavor>{flavor}</Flavor>}
|
||||
</>}
|
||||
content={<>
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity {...props} />
|
||||
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
|
||||
{unique && <Unique>{unique}</Unique>}
|
||||
{flavor && <Flavor>{flavor}</Flavor>}
|
||||
<Typography>Art By: {card.gsx$artist}</Typography>
|
||||
</>}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default BattlegearCard;
|
||||
113
src/components/_mobile/collection/CardBase.tsx
Normal file
113
src/components/_mobile/collection/CardBase.tsx
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
import { Box, Card, CardMedia, CardContent, Typography, styled, useTheme } from '@mui/material';
|
||||
import React from 'react';
|
||||
|
||||
import { Card as ChaoticCard } from "../../common/definitions";
|
||||
import { RarityIcon } from '../../Snippets';
|
||||
import API from '../../SpreadsheetData';
|
||||
|
||||
export type statsType = "avg" | "min" | "max";
|
||||
|
||||
export interface chaoticCardProps<T extends ChaoticCard> {
|
||||
card: T
|
||||
ext: boolean
|
||||
stats: statsType
|
||||
hideStats: boolean
|
||||
extend: (card: ChaoticCard | null) => void
|
||||
}
|
||||
|
||||
export interface CardBase<T extends ChaoticCard> {
|
||||
(props: chaoticCardProps<T>): JSX.Element
|
||||
}
|
||||
|
||||
|
||||
type componentProps = chaoticCardProps<ChaoticCard> & {
|
||||
left: JSX.Element
|
||||
right: JSX.Element
|
||||
content: JSX.Element
|
||||
right2?: JSX.Element
|
||||
imageCover?: JSX.Element
|
||||
}
|
||||
|
||||
export const CardComponent = (
|
||||
{ card, ext, extend, imageCover, left, right, content, right2 }: componentProps
|
||||
) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const loc = card.gsx$type === "Locations";
|
||||
|
||||
return (ext === false)
|
||||
? (
|
||||
<Card sx={{ display: 'flex',
|
||||
[theme.breakpoints.down('md')]: { flexWrap: 'wrap', alignItems: "flex-start" }
|
||||
}} raised>
|
||||
<CardMedia
|
||||
component="img"
|
||||
sx={{ width: "96px" }}
|
||||
height="100px"
|
||||
image={API.base_image + (card.gsx$thumb||API.thumb_missing)}
|
||||
alt={`${card.gsx$name} thumb`}
|
||||
onClick={() => extend(card)}
|
||||
/>
|
||||
<Box sx={{ marginLeft: .5, marginRight: .5, minWidth: "242px" }}>
|
||||
{left}
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", flexGrow: 1 }}>
|
||||
<Box sx={{ marginRight: "auto", flexGrow: 1 }}>
|
||||
{right}
|
||||
</Box>
|
||||
{right2 && <Box sx={{ float: "right" }}>
|
||||
{right2}
|
||||
</Box>}
|
||||
</Box>
|
||||
</Card>
|
||||
) : (
|
||||
<Card raised>
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', alignItems: "flex-start" }}>
|
||||
<CardMedia
|
||||
component="img"
|
||||
sx={{ width: (loc ? "350px" : "250px") }}
|
||||
height={loc ? "250" : "350"}
|
||||
image={API.cardImage(card)}
|
||||
alt={`${card.gsx$name} card`}
|
||||
onClick={() => extend(null)}
|
||||
/>
|
||||
{imageCover &&
|
||||
<div className="image-cover" onClick={() => extend(null)}>{imageCover}</div>
|
||||
}
|
||||
<CardContent sx={{
|
||||
flex: '1 0', minWidth: "310px",
|
||||
width: `calc(100% - ${loc ? " 350px" : "250px"})`,
|
||||
paddingTop: "8px",
|
||||
paddingBottom: 0,
|
||||
}}>
|
||||
{content}
|
||||
</CardContent>
|
||||
</Box>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export const Unique = styled(Typography)(() => ({
|
||||
fontWeight: "bold"
|
||||
}));
|
||||
|
||||
export const Flavor = styled(Typography)(() => ({
|
||||
fontStyle: "italic"
|
||||
}));
|
||||
|
||||
export const Rarity = (props: {card: ChaoticCard, ext: boolean}) => {
|
||||
const { card, ext } = props;
|
||||
|
||||
return (!ext) ? (
|
||||
<Typography>
|
||||
<RarityIcon size="icon20" set={card.gsx$set} rarity={card.gsx$rarity} />
|
||||
{` ${API.sets[card.gsx$set]} | ${card.gsx$rarity}`}
|
||||
</Typography>
|
||||
) : (
|
||||
<Typography>
|
||||
<RarityIcon size="icon20" set={card.gsx$set} rarity={card.gsx$rarity} />
|
||||
{` ${API.sets[card.gsx$set]} `}<span style={{ fontWeight: 'bold' }}>{`# ${card.gsx$id}`}</span>{` | ${card.gsx$rarity}`}
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
|
||||
134
src/components/_mobile/collection/Creature.tsx
Normal file
134
src/components/_mobile/collection/Creature.tsx
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
import { Typography, styled } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { Creature } from "../../common/definitions";
|
||||
import { Name, TribeIcon, MugicIcon, ElementIcon, DisciplineIcon } from '../../Snippets';
|
||||
import { abilityText } from '../../Snippets/abilityText';
|
||||
import { uniqueText } from '../../Snippets/uniqueText';
|
||||
import { CardBase, CardComponent, Unique, Flavor, Rarity } from "./CardBase";
|
||||
|
||||
const TribeLine = ({ card }: {card: Creature}) => {
|
||||
let types = card.gsx$types;
|
||||
|
||||
// Moves "Past" in front of tribe due to db entry order
|
||||
let past = false;
|
||||
if (types.toLowerCase().includes("past")) {
|
||||
past = true;
|
||||
types = types.replace(/past /i, '');
|
||||
}
|
||||
const line = ` ${ past ? "Past " : "" }${types}`;
|
||||
|
||||
return <Typography><TribeIcon tribe={card.gsx$tribe} />{line}</Typography>;
|
||||
};
|
||||
|
||||
const MugicCounter = ({ card }: { card: Creature }) => {
|
||||
const mugic = [] as JSX.Element[];
|
||||
for (let i = 0; i < Number(card.gsx$mugicability); i++) {
|
||||
mugic.push(<MugicIcon key={i} tribe={card.gsx$tribe} />);
|
||||
}
|
||||
|
||||
return <>{mugic}</>;
|
||||
};
|
||||
|
||||
const Brainwashed = styled(Typography)(() => ({
|
||||
borderRadius: "3px",
|
||||
backgroundColor: "#dcdddf",
|
||||
color: "black"
|
||||
}));
|
||||
|
||||
const Stat = styled(Typography)(() => ({
|
||||
width: "44px",
|
||||
lineHeight: "normal",
|
||||
textAlign: "right"
|
||||
}));
|
||||
|
||||
const CreatureCard: CardBase<Creature> = (props) => {
|
||||
const { card, stats, hideStats } = props;
|
||||
const ability = abilityText({ ability: card.gsx$ability, tribe: card.gsx$tribe, size: "icon16" });
|
||||
const brainwashed = abilityText({ ability: card.gsx$brainwashed, tribe: card.gsx$tribe, size: "icon16" });
|
||||
const unique = uniqueText({ data: { unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }});
|
||||
const flavor = card.gsx$flavortext;
|
||||
|
||||
const stat_range = (stat: string) => {
|
||||
const name = card.gsx$name;
|
||||
if (name && name == "Aa'une the Oligarch, Avatar") return Number(stat);
|
||||
if (stats == "min") return Number(stat) - 10;
|
||||
if (stats == "max") return Number(stat) + 10;
|
||||
return Number(stat);
|
||||
};
|
||||
|
||||
const energy_range = (energy: string) => {
|
||||
const name = card.gsx$name;
|
||||
if (name && name == "Aa'une the Oligarch, Avatar") return Number(energy);
|
||||
if (stats == "min") return Number(energy) - 5;
|
||||
if (stats == "max") return Number(energy) + 5;
|
||||
return Number(energy);
|
||||
};
|
||||
|
||||
const courage = stat_range(card.gsx$courage);
|
||||
const power = stat_range(card.gsx$power);
|
||||
const wisdom = stat_range(card.gsx$wisdom);
|
||||
const speed = stat_range(card.gsx$speed);
|
||||
const energy = energy_range(card.gsx$energy);
|
||||
|
||||
return (
|
||||
<CardComponent {...props}
|
||||
left={<>
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity {...props} />
|
||||
<TribeLine card={card} />
|
||||
<Typography>
|
||||
<ElementIcon element="fire" value={card.gsx$elements.toLowerCase().indexOf("fire") >=0} />
|
||||
<ElementIcon element="air" value={card.gsx$elements.toLowerCase().indexOf("air") >=0} />
|
||||
<ElementIcon element="earth" value={card.gsx$elements.toLowerCase().indexOf("earth") >=0} />
|
||||
<ElementIcon element="water" value={card.gsx$elements.toLowerCase().indexOf("water") >=0} />
|
||||
</Typography>
|
||||
<MugicCounter card={card} />
|
||||
</>}
|
||||
right={<>
|
||||
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
|
||||
{brainwashed && <Brainwashed>{brainwashed}</Brainwashed>}
|
||||
{unique && <Unique>{unique}</Unique>}
|
||||
{card.gsx$types.includes("Chieftain") &&
|
||||
<Flavor>(Minions use Brainwashed text. Minions may only play Generic Mugic.)</Flavor>
|
||||
}
|
||||
{flavor && <Flavor>{flavor}</Flavor>}
|
||||
</>}
|
||||
right2={<>
|
||||
<Stat>{courage}<DisciplineIcon discipline="courage" /></Stat>
|
||||
<Stat>{power}<DisciplineIcon discipline="power" /></Stat>
|
||||
<Stat>{wisdom}<DisciplineIcon discipline="wisdom" /></Stat>
|
||||
<Stat>{speed}<DisciplineIcon discipline="speed" /></Stat>
|
||||
<Stat sx={{ fontWeight: "bold" }}>{energy}<span style={{ display: "inline-block", width: "16px" }}></span></Stat>
|
||||
</>}
|
||||
{...((!hideStats) ? { imageCover: (
|
||||
<div>
|
||||
<span key="courage" {...(courage >= 100 ? { className: "long" } : null)}>{courage}</span>
|
||||
<span key="power" {...(power >= 100 ? { className: "long" } : null)}>{power}</span>
|
||||
<span key="wisdom" {...(wisdom >= 100 ? { className: "long" } : null)}>{wisdom}</span>
|
||||
<span key="speed" {...(speed >= 100 ? { className: "long" } : null)}>{speed}</span>
|
||||
<span key="energy" {...(energy >= 100 ? { className: "long" } : null)}>{energy}</span>
|
||||
</div>
|
||||
) }
|
||||
: undefined)}
|
||||
content={<>
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity {...props} />
|
||||
<span>{stat_range(card.gsx$courage)} <DisciplineIcon discipline="courage" /></span>
|
||||
<span>{stat_range(card.gsx$power)} <DisciplineIcon discipline="power" /></span>
|
||||
<span>{stat_range(card.gsx$wisdom)} <DisciplineIcon discipline="wisdom" /></span>
|
||||
<span>{stat_range(card.gsx$speed)} <DisciplineIcon discipline="speed" /></span>
|
||||
<span style={{ fontWeight: 'bold' }}>{energy_range(card.gsx$energy)}</span>
|
||||
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
|
||||
{brainwashed && <Brainwashed>{brainwashed}</Brainwashed>}
|
||||
{unique && <Unique>{unique}</Unique>}
|
||||
{card.gsx$types.includes("Chieftain") &&
|
||||
<Flavor>(Minions use Brainwashed text. Minions may only play Generic Mugic.)</Flavor>
|
||||
}
|
||||
{flavor && <Flavor>{flavor}</Flavor>}
|
||||
<Typography>Art By: {card.gsx$artist}</Typography>
|
||||
</>}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreatureCard;
|
||||
41
src/components/_mobile/collection/Location.tsx
Normal file
41
src/components/_mobile/collection/Location.tsx
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { Typography } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { Location } from '../../common/definitions';
|
||||
import { InitiativeIcon, LocationIcon, Name } from '../../Snippets';
|
||||
import { abilityText } from '../../Snippets/abilityText';
|
||||
import { uniqueText } from '../../Snippets/uniqueText';
|
||||
import { CardBase, CardComponent, Unique, Flavor, Rarity } from './CardBase';
|
||||
|
||||
const LocationCard: CardBase<Location> = (props) => {
|
||||
const { card } = props;
|
||||
const ability = abilityText({ ability: card.gsx$ability, size: "icon16" });
|
||||
const unique = uniqueText({ data: { unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }});
|
||||
const flavor = card.gsx$flavortext;
|
||||
|
||||
return (
|
||||
<CardComponent {...props}
|
||||
left={<>
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity {...props} />
|
||||
<Typography><LocationIcon size="icon20" /> Location{card.gsx$types.length > 0 ? ` - ${card.gsx$types}` : null}</Typography>
|
||||
<Typography>{`Initiative: `}<InitiativeIcon initiative={card.gsx$initiative} />{` ${card.gsx$initiative}`}</Typography>
|
||||
</>}
|
||||
right={<>
|
||||
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
|
||||
{unique && <Unique>{unique}</Unique>}
|
||||
{flavor && <Flavor>{flavor}</Flavor>}
|
||||
</>}
|
||||
content={<>
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity {...props} />
|
||||
<Typography>{`Initiative: `}<InitiativeIcon initiative={card.gsx$initiative} />{` ${card.gsx$initiative}`}</Typography>
|
||||
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
|
||||
{unique && <Unique>{unique}</Unique>}
|
||||
{flavor && <Flavor>{flavor}</Flavor>}
|
||||
<Typography>Art By: {card.gsx$artist}</Typography>
|
||||
</>}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default LocationCard;
|
||||
66
src/components/_mobile/collection/Mugic.tsx
Normal file
66
src/components/_mobile/collection/Mugic.tsx
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { Typography } from "@mui/material";
|
||||
import React from "react";
|
||||
import { Mugic } from "../../common/definitions";
|
||||
import { Name, TribeIcon, MugicIcon } from "../../Snippets";
|
||||
import { abilityText } from "../../Snippets/abilityText";
|
||||
import { uniqueText } from "../../Snippets/uniqueText";
|
||||
import { CardBase, CardComponent, Unique, Flavor, Rarity } from "./CardBase";
|
||||
|
||||
|
||||
const MugicCounter = ({ card }: { card: Mugic }) => {
|
||||
const mugicCounters = [] as JSX.Element[];
|
||||
if (Number(card.gsx$cost) === 0) {
|
||||
mugicCounters.push(<MugicIcon tribe={card.gsx$tribe} key={0} amount={"0"}/>);
|
||||
}
|
||||
else if (card.gsx$cost.toLowerCase() == 'x') {
|
||||
mugicCounters.push(<MugicIcon tribe={card.gsx$tribe} key={0} amount={"x"}/>);
|
||||
}
|
||||
else {
|
||||
if (Number(card.gsx$cost) > 5) {
|
||||
mugicCounters.push(<MugicIcon tribe={card.gsx$tribe} key={0} amount={card.gsx$cost} />);
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < Number(card.gsx$cost); i++) {
|
||||
mugicCounters.push(<MugicIcon tribe={card.gsx$tribe} key={i} />);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return <>{mugicCounters}</>;
|
||||
};
|
||||
|
||||
const MugicCard: CardBase<Mugic> = (props) => {
|
||||
const { card } = props;
|
||||
const ability = abilityText({ ability: card.gsx$ability, tribe: card.gsx$tribe, size: "icon16" });
|
||||
const unique = uniqueText({ data: { unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }});
|
||||
const flavor = card.gsx$flavortext;
|
||||
|
||||
return (
|
||||
<CardComponent {...props}
|
||||
left={<>
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity {...props} />
|
||||
<Typography><TribeIcon size="icon20" tribe={card.gsx$tribe} /> Mugic - {card.gsx$tribe}</Typography>
|
||||
<Typography><MugicCounter card={card}/></Typography>
|
||||
</>
|
||||
}
|
||||
right={<>
|
||||
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
|
||||
{unique && <Unique>{unique}</Unique>}
|
||||
{flavor && <Flavor>{flavor}</Flavor>}
|
||||
</>}
|
||||
content={<>
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity {...props} />
|
||||
<Typography sx={{ whiteSpace: "pre-line" }}>{ability}</Typography>
|
||||
{unique && <Unique>{unique}</Unique>}
|
||||
{flavor && <Flavor>{flavor}</Flavor>}
|
||||
<Typography>Art By: {card.gsx$artist}</Typography>
|
||||
<Typography>Notes: {card.gsx$notes}</Typography>
|
||||
</>}
|
||||
/>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
export default MugicCard;
|
||||
159
src/components/_mobile/collection/NavMenu.tsx
Normal file
159
src/components/_mobile/collection/NavMenu.tsx
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
import { Drawer, IconButton, MenuItem, MenuList, Toolbar, useTheme } from '@mui/material';
|
||||
import React, { useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const NavMenu = () => {
|
||||
const theme = useTheme();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleToggle = () => {
|
||||
setOpen((prevOpen) => !prevOpen);
|
||||
};
|
||||
|
||||
return (<>
|
||||
<IconButton
|
||||
size="large"
|
||||
edge="start"
|
||||
color="inherit"
|
||||
aria-label="menu"
|
||||
onClick={handleToggle}
|
||||
sx={{ mr: 1, p: 2,
|
||||
[theme.breakpoints.up("sm")]: {
|
||||
margin: "auto",
|
||||
},
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
// top: `-${theme.spacing(2)}`,
|
||||
marginBottom: 0,
|
||||
marginLeft: 1
|
||||
}
|
||||
}}
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
<Drawer
|
||||
anchor="left"
|
||||
open={open}
|
||||
onClose={handleToggle}
|
||||
>
|
||||
<Toolbar />
|
||||
<MenuList
|
||||
autoFocusItem={open}
|
||||
id="composition-menu"
|
||||
aria-labelledby="composition-button"
|
||||
>
|
||||
<MenuItem component={Link} to="/">Home</MenuItem>
|
||||
<MenuItem onClick={handleToggle}>Collection</MenuItem>
|
||||
<MenuItem component={Link} to="/portal/">Portal</MenuItem>
|
||||
<MenuItem component="a" href="https://chaoticbackup.forumotion.com">Forum</MenuItem>
|
||||
<MenuItem component="a" href="https://chaoticrecode.com">Play</MenuItem>
|
||||
</MenuList>
|
||||
</Drawer>
|
||||
</>);
|
||||
};
|
||||
|
||||
export default NavMenu;
|
||||
|
||||
/*
|
||||
const NavMenu = () => {
|
||||
const theme = useTheme();
|
||||
const [open, setOpen] = useState(false);
|
||||
const anchorRef = React.useRef<HTMLButtonElement>(null);
|
||||
const prevOpen = React.useRef(open);
|
||||
|
||||
const handleToggle = () => {
|
||||
setOpen((prevOpen) => !prevOpen);
|
||||
};
|
||||
|
||||
function handleListKeyDown(event: React.KeyboardEvent) {
|
||||
if (event.key === 'Escape') {
|
||||
setOpen(false);
|
||||
}
|
||||
}
|
||||
|
||||
const handleClose = (event: Event | React.SyntheticEvent) => {
|
||||
if (anchorRef.current &&
|
||||
anchorRef.current.contains(event.target as HTMLElement)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
// return focus to the button when we transitioned from !open -> open
|
||||
useEffect(() => {
|
||||
if (prevOpen.current === true && open === false) {
|
||||
anchorRef.current!.focus();
|
||||
}
|
||||
|
||||
prevOpen.current = open;
|
||||
}, [open]);
|
||||
|
||||
// TODO change from popper to drawer
|
||||
|
||||
return (<>
|
||||
<IconButton
|
||||
size="large"
|
||||
edge="start"
|
||||
color="inherit"
|
||||
aria-label="menu"
|
||||
ref={anchorRef}
|
||||
onClick={handleToggle}
|
||||
sx={{ mr: 1, p: 2,
|
||||
[theme.breakpoints.down("sm")]: {
|
||||
top: `-${theme.spacing(2)}`,
|
||||
marginBottom: 0
|
||||
}
|
||||
}}
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
<Popper
|
||||
open={open}
|
||||
anchorEl={anchorRef.current}
|
||||
role={undefined}
|
||||
placement="bottom-start"
|
||||
transition
|
||||
disablePortal
|
||||
popperOptions={{
|
||||
modifiers: [
|
||||
{
|
||||
name: 'offset',
|
||||
options: {
|
||||
offset: [0, 16],
|
||||
},
|
||||
},
|
||||
]
|
||||
}}
|
||||
>
|
||||
{({ TransitionProps, placement }) => (
|
||||
<Grow
|
||||
{...TransitionProps}
|
||||
style={{
|
||||
transformOrigin: (placement === 'bottom-start') ? 'left top' : 'left bottom',
|
||||
}}
|
||||
>
|
||||
<Paper>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<MenuList
|
||||
autoFocusItem={open}
|
||||
id="composition-menu"
|
||||
aria-labelledby="composition-button"
|
||||
onKeyDown={handleListKeyDown}
|
||||
>
|
||||
<MenuItem component={Link} to="/">Home</MenuItem>
|
||||
<MenuItem onClick={handleClose}>Collection</MenuItem>
|
||||
<MenuItem component={Link} to="/portal/">Portal</MenuItem>
|
||||
<MenuItem component="a" href="https://chaoticbackup.forumotion.com">Forum</MenuItem>
|
||||
<MenuItem component="a" href="https://chaoticrecode.com">Play</MenuItem>
|
||||
</MenuList>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Grow>
|
||||
)}
|
||||
</Popper>
|
||||
</>);
|
||||
};
|
||||
|
||||
*/
|
||||
455
src/components/_mobile/collection/Search.tsx
Normal file
455
src/components/_mobile/collection/Search.tsx
Normal file
|
|
@ -0,0 +1,455 @@
|
|||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import {
|
||||
Accordion as MuiAccordion, AccordionDetails, AccordionSummary, Box, Button, Checkbox as MuiCheckbox, Dialog, DialogActions, DialogContent,
|
||||
Fab, FormControlLabel as MuiFCL, FormGroup, InputAdornment, styled, TextField, ToggleButton, ToggleButtonGroup,
|
||||
Typography, useMediaQuery, useTheme, Zoom
|
||||
} from '@mui/material';
|
||||
import React, { FormEvent, useEffect, useMemo, useReducer, useRef, useState } from 'react';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
import search_api from '../../collection/search/search';
|
||||
import { ElementIcon, TribeIcon } from '../../Snippets';
|
||||
import API, { sets } from '../../SpreadsheetData/API';
|
||||
|
||||
const Accordion = styled(MuiAccordion)(() => ({
|
||||
"&.Mui-expanded": {
|
||||
margin: 0
|
||||
}
|
||||
}));
|
||||
|
||||
const Checkbox = styled(MuiCheckbox)(() => ({
|
||||
padding: "4px"
|
||||
}));
|
||||
|
||||
const FormControlLabel = styled(MuiFCL)(() => ({
|
||||
marginLeft: "-4px",
|
||||
marginRight: "8px"
|
||||
}));
|
||||
|
||||
const initInput = (() => {
|
||||
/* @ts-ignore */
|
||||
const cardSets: {[key in keyof typeof sets]: boolean} = {};
|
||||
for (const key in sets) cardSets[key.toLowerCase()] = false;
|
||||
|
||||
return {
|
||||
name: "",
|
||||
text: "",
|
||||
subtypes: "",
|
||||
flavor: true,
|
||||
sets: cardSets,
|
||||
types: { attack: false, battlegear: false, creature: false, location: false, mugic: false },
|
||||
rarity: { common: false, uncommon: false, rare: false, 'super rare': false, 'ultra rare': false, promo: false },
|
||||
tribes: { danian: false, 'm\'arrillian': false, mipedian: false, overworld: false, underworld: false, generic: false },
|
||||
elements: { fire: false, air: false, earth: false, water: false, none: false, and: false },
|
||||
disciplines: { courage: '', power: '', wisdom: '', speed: '', max: false },
|
||||
energy: { min: '', max: '' },
|
||||
mcbp: { min: '', max: '' },
|
||||
mull: { unique: false, loyal: false, legendary: false, mixed: false },
|
||||
gender: { ambiguous: false, female: false, male: false }
|
||||
};
|
||||
})();
|
||||
|
||||
const initExpand = ({
|
||||
disciplines: true,
|
||||
energy: true,
|
||||
bpmc: true,
|
||||
types: true,
|
||||
rarity: false,
|
||||
sets: false
|
||||
});
|
||||
|
||||
const queryList = ["sets", "types", "rarity", "tribes", "elements", "mull", "gender"];
|
||||
|
||||
const inputReducer = (state: typeof initInput, newState: Partial<typeof initInput>) => {
|
||||
return { ...state, ...newState };
|
||||
};
|
||||
|
||||
const expandReducer = (state: typeof initExpand, newState: Partial<typeof initExpand>) => {
|
||||
return { ...state, ...newState };
|
||||
};
|
||||
|
||||
function Search ({ setContent, setInfo }) {
|
||||
const theme = useTheme();
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
const prevLocation = useRef<any>(location);
|
||||
const [input, dispatchInput] = useReducer(inputReducer, initInput, (input) => parseQuery(input, location));
|
||||
const [expand, dispatchExpand] = useReducer(expandReducer, initExpand, parseExpand);
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const fullscreen = useMediaQuery("@media (max-width:530px)");
|
||||
|
||||
useEffect(() => {
|
||||
setInfo({ 'text': 'Loading..' });
|
||||
API.LoadDB([{ 'cards': 'attacks' }, { 'cards': 'battlegear' }, { 'cards': 'creatures' }, { 'cards': 'locations' }, { 'cards': 'mugic' }])
|
||||
.then(() => {
|
||||
setLoaded(true);
|
||||
handleSearch();
|
||||
})
|
||||
.catch(() => {});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (location != prevLocation.current) {
|
||||
prevLocation.current = location;
|
||||
dispatchInput(parseQuery(initInput, location));
|
||||
}
|
||||
}, [input, location]);
|
||||
|
||||
|
||||
const cleanInput = () => {
|
||||
dispatchInput({ ...initInput });
|
||||
};
|
||||
|
||||
const handleSearch = (event?: FormEvent) => {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
updateQuery(input, history);
|
||||
setOpen(false);
|
||||
}
|
||||
|
||||
const results = search_api(input);
|
||||
|
||||
setContent(results);
|
||||
if (results.length === 0) {
|
||||
setInfo({ 'text': 'No Results Found' });
|
||||
} else {
|
||||
setInfo({});
|
||||
}
|
||||
};
|
||||
|
||||
const handleChange = (name: string, obj?: string) => (event: {target: HTMLInputElement | HTMLTextAreaElement}) => {
|
||||
const { target } = event;
|
||||
const value = target.type === 'checkbox' ? (target as HTMLInputElement).checked : target.value;
|
||||
dispatchInput({
|
||||
...((!obj) ? { [name]: value } : { [obj]: { ...input[obj], [name]: value }})
|
||||
});
|
||||
};
|
||||
|
||||
const handleExpand = (field: keyof typeof initExpand) => (event: React.SyntheticEvent, isExpanded: boolean) => {
|
||||
dispatchExpand({ [field]: isExpanded });
|
||||
localStorage.setItem("collapsed", JSON.stringify({ ...expand, [field]: isExpanded }));
|
||||
};
|
||||
|
||||
const handleOpen = () => {setOpen(true)};
|
||||
|
||||
const handleClose = () => {setOpen(false)};
|
||||
|
||||
const generate = (type: string, row: boolean, label: (item: string) => React.ReactNode) => {
|
||||
return Object.keys(input[type]).map((item, i) => (
|
||||
<FormControlLabel style={{ display: "inline" }} key={i} control={
|
||||
<Checkbox checked={input[type][item]} onChange={handleChange(item, type)} />
|
||||
} label={label(item)} />
|
||||
));
|
||||
};
|
||||
|
||||
const tribes = useMemo(() => (
|
||||
generate("tribes", true, (item) =>
|
||||
<TribeIcon size="icon20" tribe={item} />
|
||||
)
|
||||
), [input.tribes]);
|
||||
|
||||
const elements = useMemo(() => (
|
||||
generate("elements", true, (item) =>
|
||||
<ElementIcon size="icon20" element={item} value="5" />
|
||||
).slice(0, -2)
|
||||
), [input.elements]);
|
||||
|
||||
const sets = useMemo(() => (
|
||||
generate("sets", false, (set) =>
|
||||
API.sets[set.toUpperCase()]
|
||||
)
|
||||
), [input.sets]);
|
||||
|
||||
const types = useMemo(() => (
|
||||
generate("types", false, (type) =>
|
||||
`${type.charAt(0).toUpperCase()}${type.slice(1)}`
|
||||
)
|
||||
), [input.types]);
|
||||
|
||||
const rarity = useMemo(() => (
|
||||
generate("rarity", false, (item) =>
|
||||
item.split(" ").map((st) => `${st.charAt(0).toUpperCase()}${st.slice(1)}`).join(" ")
|
||||
)
|
||||
), [input.rarity]);
|
||||
|
||||
const disciplines = useMemo(() => (
|
||||
Object.keys(input.disciplines).slice(0, 4).map((item) => (
|
||||
<TextField key={item}
|
||||
value={input.disciplines[item]}
|
||||
onChange={handleChange(item, "disciplines")}
|
||||
sx={{
|
||||
"@media (max-width:530px)": {
|
||||
width: "25%"
|
||||
},
|
||||
"@media (min-width:530px)": {
|
||||
width: "20%"
|
||||
},
|
||||
"& .MuiInputBase-input": { pt: 1, pb: 1 }
|
||||
}}
|
||||
InputProps={{
|
||||
inputProps: { min: 0 },
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<img className="icon20" style={{ verticalAlign: 'middle', padding: "0px 2px" }} src={`/public/img/icons/disciplines/${item}.png`} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
))
|
||||
), [input.disciplines]);
|
||||
|
||||
const transitionDuration = {
|
||||
enter: theme.transitions.duration.enteringScreen,
|
||||
exit: theme.transitions.duration.leavingScreen,
|
||||
};
|
||||
|
||||
return (<>
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
fullScreen={fullscreen}
|
||||
>
|
||||
{(loaded === true) && (<>
|
||||
<DialogContent>
|
||||
<Box component="form"
|
||||
id='search-form'
|
||||
onSubmit={handleSearch}
|
||||
>
|
||||
<FormGroup>
|
||||
<TextField
|
||||
label="Name"
|
||||
value={input.name}
|
||||
onChange={handleChange("name")}
|
||||
/>
|
||||
<TextField
|
||||
label="Text"
|
||||
value={input.text}
|
||||
onChange={handleChange("text")}
|
||||
/>
|
||||
<TextField
|
||||
label="Subtypes | Initiative"
|
||||
value={input.subtypes}
|
||||
onChange={handleChange("subtypes")}
|
||||
/>
|
||||
<FormControlLabel control={
|
||||
<Checkbox checked={!input.flavor} onChange={(e) => {dispatchInput({ flavor: !e.target.checked })}} />
|
||||
} label="Ignore Flavortext & Artist" />
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
<FormControlLabel control={
|
||||
<Checkbox checked={input.mull.unique} onChange={handleChange("unique", "mull")} />
|
||||
} label="Unique" />
|
||||
<FormControlLabel control={
|
||||
<Checkbox checked={input.mull.loyal} onChange={handleChange("loyal", "mull")} />
|
||||
} label="Loyal" />
|
||||
<FormControlLabel control={
|
||||
<Checkbox checked={input.mull.legendary} onChange={handleChange("legendary", "mull")} />
|
||||
} label="Legendary" />
|
||||
<FormControlLabel control={
|
||||
<Checkbox checked={input.mull.mixed} onChange={handleChange("mixed", "mull")} />
|
||||
} label="Non-Loyal" />
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
{tribes}
|
||||
</FormGroup>
|
||||
<FormGroup row>
|
||||
{elements}
|
||||
<FormControlLabel control={
|
||||
<Checkbox checked={input.elements.none} onChange={handleChange("none", "elements")} />
|
||||
} label="None" />
|
||||
</FormGroup>
|
||||
<ToggleButtonGroup
|
||||
value={input.elements.and}
|
||||
exclusive
|
||||
sx={{ mb: 1 }}
|
||||
onChange={(e, value) => {dispatchInput({ "elements": { ...input.elements, "and": value }})} }
|
||||
>
|
||||
<ToggleButton value={false} sx={{ paddingTop: 0, paddingBottom: 0 }}>{(input.elements.none) ? "none" : "or"}</ToggleButton>
|
||||
<ToggleButton value={true} sx={{ paddingTop: 0, paddingBottom: 0 }}>{(input.elements.none) ? "only" : "and"}</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
<FormGroup row>
|
||||
{disciplines}
|
||||
<FormControlLabel labelPlacement="start"
|
||||
sx={{
|
||||
"@media (max-width:530px)": {
|
||||
marginLeft: "0"
|
||||
},
|
||||
"@media (min-width:530px)": {
|
||||
marginLeft: "4px"
|
||||
}
|
||||
}} control={
|
||||
<Checkbox checked={input.disciplines.max} onChange={handleChange("max", "disciplines")} />
|
||||
} label="Max" />
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<Typography>Energy</Typography>
|
||||
<FormGroup row>
|
||||
<TextField size="small" sx={{ width: "35%" }} label="Min" value={input.energy.min} onChange={handleChange("min", "energy")} />
|
||||
<TextField size="small" sx={{ width: "35%" }} label="Max" value={input.energy.max} onChange={handleChange("max", "energy")} />
|
||||
</FormGroup>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<Typography>Build Points & Mugic Counters/Cost</Typography>
|
||||
<FormGroup row>
|
||||
<TextField size="small" sx={{ width: "35%" }} label="Min" value={input.mcbp.min} onChange={handleChange("min", "mcbp")} />
|
||||
<TextField size="small" sx={{ width: "35%" }} label="Max" value={input.mcbp.max} onChange={handleChange("max", "mcbp")} />
|
||||
</FormGroup>
|
||||
</FormGroup>
|
||||
<Accordion expanded={expand.types}
|
||||
onChange={handleExpand("types")}
|
||||
>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>Card Type</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<FormGroup>{types}</FormGroup>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
<Accordion expanded={expand.rarity}
|
||||
onChange={handleExpand("rarity")}
|
||||
>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>Rarity</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<FormGroup>{rarity}</FormGroup>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
<Accordion expanded={expand.sets}
|
||||
onChange={handleExpand("sets")}
|
||||
>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography>Sets</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<FormGroup>{sets}</FormGroup>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ justifyContent: "flex-start" }}>
|
||||
<Button type="submit" form="search-form" variant="outlined">Submit</Button>
|
||||
<Button variant="outlined" onClick={() => cleanInput()}>Reset</Button>
|
||||
<Button onClick={handleClose} sx={{ marginLeft: "auto !important" }}>Close</Button>
|
||||
</DialogActions>
|
||||
</>)}
|
||||
</Dialog>
|
||||
<Zoom
|
||||
in={!open}
|
||||
timeout={transitionDuration}
|
||||
style={{
|
||||
transitionDelay: `${!open ? transitionDuration.exit : 0}ms`,
|
||||
}}
|
||||
unmountOnExit
|
||||
>
|
||||
<Fab aria-label="search"
|
||||
sx={{ position: 'fixed', bottom: 16, right: 16 }}
|
||||
onClick={handleOpen}
|
||||
>
|
||||
<SearchIcon />
|
||||
</Fab>
|
||||
</Zoom>
|
||||
</>);
|
||||
}
|
||||
|
||||
const parseQuery = (init: typeof initInput, location) => {
|
||||
const input = Object.assign({}, init);
|
||||
const queryString = location.search.toLowerCase();
|
||||
|
||||
const query = {} as any;
|
||||
const pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
|
||||
for (let i = 0; i < pairs.length; i++) {
|
||||
const pair = pairs[i].split('=');
|
||||
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
|
||||
}
|
||||
|
||||
// query -> input
|
||||
queryList.forEach((d) => {
|
||||
if (query[d]) {
|
||||
query[d].split(',').map(item => {
|
||||
input[d][item] = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (query.hasOwnProperty('name')) input.name = query.name;
|
||||
if (query.hasOwnProperty('text')) input.text = query.text;
|
||||
if (query.hasOwnProperty('subtypes')) input.subtypes = query.subtypes;
|
||||
if (query.hasOwnProperty('courage')) input.disciplines.courage = query.courage;
|
||||
if (query.hasOwnProperty('power')) input.disciplines.power = query.power;
|
||||
if (query.hasOwnProperty('wisdom')) input.disciplines.wisdom = query.wisdom;
|
||||
if (query.hasOwnProperty('speed')) input.disciplines.speed = query.speed;
|
||||
if (query.hasOwnProperty('disc_max')) input.disciplines.max = !!query.disc_max;
|
||||
if (query.hasOwnProperty('energy')) {
|
||||
const q = query.energy.split(',');
|
||||
if (q[0] >= 0) input.energy.min = q[0];
|
||||
if (q[1] >= 0) input.energy.max = q[1];
|
||||
}
|
||||
if (query.hasOwnProperty('mcbp')) {
|
||||
const q = query.mcbp.split(',');
|
||||
if (q[0] >= 0) input.mcbp.min = q[0];
|
||||
if (q[1] >= 0) input.mcbp.max = q[1];
|
||||
}
|
||||
|
||||
return input;
|
||||
};
|
||||
|
||||
const updateQuery = (input, history) => {
|
||||
let queryString = "";
|
||||
|
||||
queryList.forEach(query => {
|
||||
let temp = "";
|
||||
Object.keys(input[query]).forEach((item) => {
|
||||
if (input[query][item] == true) temp += `${item},`;
|
||||
});
|
||||
if (temp.length > 0) {
|
||||
queryString += `${query}=${temp.replace(/\,$/, '&')}`;
|
||||
}
|
||||
});
|
||||
|
||||
if (input.name) queryString += `name=${encodeURIComponent(input.name)}&`;
|
||||
if (input.text) queryString += `text=${encodeURIComponent(input.text)}&`;
|
||||
if (input.subtypes) queryString += `subtypes=${encodeURIComponent(input.subtypes)}&`;
|
||||
if (input.disciplines.courage > 0) queryString += `courage=${input.disciplines.courage}&`;
|
||||
if (input.disciplines.power > 0) queryString += `power=${input.disciplines.power}&`;
|
||||
if (input.disciplines.wisdom > 0) queryString += `wisdom=${input.disciplines.wisdom}&`;
|
||||
if (input.disciplines.speed > 0) queryString += `speed=${input.disciplines.speed}&`;
|
||||
if (input.disciplines.max) queryString += "disc_max=true&";
|
||||
if (input.energy.min != "" || input.energy.max != "") {
|
||||
queryString += "energy=";
|
||||
if (input.energy.min != "" && input.energy.min >= 0) queryString += input.energy.min;
|
||||
queryString += ",";
|
||||
if (input.energy.max != "" && input.energy.max >= 0) queryString += input.energy.max;
|
||||
queryString += "&";
|
||||
}
|
||||
if (input.mcbp.min != "" || input.mcbp.max != "") {
|
||||
queryString += "mcbp=";
|
||||
if (input.mcbp.min != "" && input.mcbp.min >= 0) queryString += input.mcbp.min;
|
||||
queryString += ",";
|
||||
if (input.mcbp.max != "" && input.mcbp.max >= 0) queryString += input.mcbp.max;
|
||||
queryString += "&";
|
||||
}
|
||||
|
||||
// Strip trailing &
|
||||
queryString = queryString.replace(/\&$/, '');
|
||||
|
||||
// Push to URL
|
||||
history.push(`/collection/?${queryString}`);
|
||||
};
|
||||
|
||||
const parseExpand = (init: typeof initExpand) => {
|
||||
let input = Object.assign({}, init);
|
||||
|
||||
const collapsed = localStorage.getItem("collapsed");
|
||||
if (collapsed) {
|
||||
input = { ...input, ...JSON.parse(collapsed) };
|
||||
}
|
||||
|
||||
return input;
|
||||
};
|
||||
|
||||
export default Search;
|
||||
91
src/components/_mobile/collection/collection.scss
Normal file
91
src/components/_mobile/collection/collection.scss
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
.icon14 {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.icon16 {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.icon20 {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.icon24 {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.name {
|
||||
-webkit-user-select: all;
|
||||
-moz-user-select: all;
|
||||
-ms-user-select: all;
|
||||
user-select: all;
|
||||
}
|
||||
|
||||
.name .subname::before {
|
||||
content: "\a ";
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.name .subname {
|
||||
font-size: 13px;
|
||||
padding-bottom: 4px;
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
.image-cover {
|
||||
width: 250px;
|
||||
height: 350px;
|
||||
background-size: cover;
|
||||
box-sizing: content-box;
|
||||
position: absolute;
|
||||
|
||||
& > div {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
|
||||
span {
|
||||
position: relative;
|
||||
color: black;
|
||||
display: block;
|
||||
left: 28px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
|
||||
&.long {
|
||||
left: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
span:nth-of-type(1) {
|
||||
top: 222px;
|
||||
}
|
||||
span:nth-of-type(2) {
|
||||
top: 232px;
|
||||
}
|
||||
span:nth-of-type(3) {
|
||||
top: 242px;
|
||||
}
|
||||
span:nth-of-type(4) {
|
||||
top: 252px;
|
||||
}
|
||||
span:nth-of-type(5) {
|
||||
text-align: right;
|
||||
top: 260px;
|
||||
left: -17px;
|
||||
font-size: 21px;
|
||||
|
||||
&.long {
|
||||
left: -12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
301
src/components/_mobile/collection/index.tsx
Normal file
301
src/components/_mobile/collection/index.tsx
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
import {
|
||||
AppBar, Box, Card, Checkbox, createTheme, FormControl, FormControlLabel, InputLabel, MenuItem,
|
||||
Pagination, Paper, Select, SelectChangeEvent, Stack, styled, ThemeProvider, Typography, useMediaQuery
|
||||
} from '@mui/material';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Attack, Battlegear, Card as ChaoticCard, Location, Mugic, Creature } from '../../common/definitions';
|
||||
import AttackCard from './Attack';
|
||||
import BattlegearCard from './Battlegear';
|
||||
import { chaoticCardProps, statsType } from './CardBase';
|
||||
import CreatureCard from './Creature';
|
||||
import LocationCard from './Location';
|
||||
import MugicCard from './Mugic';
|
||||
import NavMenu from './NavMenu';
|
||||
import Search from './Search';
|
||||
|
||||
import './collection.scss';
|
||||
|
||||
let theme = createTheme({
|
||||
breakpoints: {
|
||||
values: {
|
||||
xs: 0,
|
||||
sm: 430,
|
||||
md: 650,
|
||||
lg: 1200,
|
||||
xl: 1536,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
theme = createTheme(theme, createTheme({
|
||||
components: {
|
||||
MuiUseMediaQuery: {
|
||||
defaultProps: {
|
||||
noSsr: true,
|
||||
},
|
||||
},
|
||||
MuiCard: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
backgroundColor: "#1F1F1F",
|
||||
color: "gray",
|
||||
marginBottom: "4px"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const CustomSelect = styled(Select)(() => ({
|
||||
'& > .MuiSelect-outlined': {
|
||||
paddingTop: "5px",
|
||||
paddingBottom: "5px"
|
||||
}
|
||||
}));
|
||||
|
||||
interface storage {
|
||||
extended?: string
|
||||
stats?: statsType
|
||||
hideStats?: string
|
||||
}
|
||||
|
||||
export default function Collection (_props) {
|
||||
const [p, sp] = useState(1);
|
||||
const [n, sn] = useState(10);
|
||||
const [ext, setExtended] = useState(false);
|
||||
const [stats, setStats] = useState<statsType>("avg");
|
||||
const [hideStats, setHideStats] = useState(false);
|
||||
const [content, setContent] = useState<ChaoticCard[]>([]);
|
||||
const [info, setInfo] = useState<{text?: string}>({});
|
||||
const [selected, setSelected] = useState<ChaoticCard | null>(null);
|
||||
const isSmall = useMediaQuery(theme.breakpoints.down("sm"), { noSsr: true });
|
||||
|
||||
useEffect(() => {
|
||||
const load = localStorage.getItem("collection");
|
||||
|
||||
if (load) {
|
||||
const { extended, stats, hideStats } = JSON.parse(load) as storage;
|
||||
if (extended !== undefined) setExtended((/true/i).test(extended));
|
||||
if (stats !== undefined) {
|
||||
if (stats == "min") setStats("min");
|
||||
if (stats == "max") setStats("max");
|
||||
}
|
||||
if (hideStats !== undefined) setHideStats(hideStats !== "false");
|
||||
}
|
||||
}, []);
|
||||
|
||||
const saveSettings = (setting: Partial<storage>) => {
|
||||
const load = localStorage.getItem("collection");
|
||||
let save: storage = {};
|
||||
if (load) {
|
||||
const rest = JSON.parse(load) as storage;
|
||||
save = { ...rest, ...setting };
|
||||
} else {
|
||||
save = setting;
|
||||
}
|
||||
localStorage.setItem("collection", JSON.stringify(save));
|
||||
};
|
||||
|
||||
const handlePerPage = (event: SelectChangeEvent<number>) => {
|
||||
sn(event.target.value as number);
|
||||
sp(1);
|
||||
};
|
||||
|
||||
const handlePage = (event: React.ChangeEvent<unknown>, value: number) => {
|
||||
sp(value);
|
||||
};
|
||||
|
||||
const handleExt = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setExtended(event.target.checked);
|
||||
saveSettings({ extended: event.target.checked.toString() });
|
||||
};
|
||||
|
||||
const hanldeStats = (event: SelectChangeEvent<statsType>) => {
|
||||
setStats(event.target.value as statsType);
|
||||
saveSettings({ stats: event.target.value as statsType });
|
||||
};
|
||||
|
||||
const handleHideStats = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setHideStats(event.target.checked);
|
||||
saveSettings({ hideStats: event.target.checked.toString() });
|
||||
};
|
||||
|
||||
const handleExtendSingle = (card: ChaoticCard | null) => {
|
||||
setSelected(card);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setSelected(null);
|
||||
}, [content]);
|
||||
|
||||
const TopMenu = () => (<>
|
||||
<Typography>{content.length} results</Typography>
|
||||
<FormControl>
|
||||
<InputLabel htmlFor="per-page">Per Page</InputLabel>
|
||||
<CustomSelect
|
||||
id="per-page"
|
||||
value={n}
|
||||
/* @ts-ignore */
|
||||
onChange={handlePerPage}
|
||||
sx={{ marginLeft: "2px", width: "70px" }}
|
||||
>
|
||||
<MenuItem value={5}>5</MenuItem>
|
||||
<MenuItem value={10}>10</MenuItem>
|
||||
<MenuItem value={25}>25</MenuItem>
|
||||
<MenuItem value={50}>50</MenuItem>
|
||||
</CustomSelect>
|
||||
</FormControl>
|
||||
<Pagination variant="outlined" shape="rounded"
|
||||
count={Math.ceil(content.length / n)}
|
||||
page={p}
|
||||
onChange={handlePage}
|
||||
sx={{ width: "350px " }}
|
||||
/>
|
||||
<FormControl>
|
||||
<InputLabel htmlFor="stats-drop">Stats</InputLabel>
|
||||
<CustomSelect
|
||||
id="stats-drop"
|
||||
value={stats}
|
||||
/* @ts-ignore */
|
||||
onChange={hanldeStats}
|
||||
sx={{ width: "106px" }}
|
||||
>
|
||||
<MenuItem value="min">Min</MenuItem>
|
||||
<MenuItem value="avg">Average</MenuItem>
|
||||
<MenuItem value="max">Max</MenuItem>
|
||||
</CustomSelect>
|
||||
</FormControl>
|
||||
<FormControlLabel
|
||||
label="Extended"
|
||||
labelPlacement="start"
|
||||
control={<Checkbox checked={ext} onChange={handleExt} />}
|
||||
sx={{
|
||||
margin: "auto 0",
|
||||
'& > .MuiCheckbox-root': {
|
||||
padding: 0
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<FormControlLabel label="Hide Stats"
|
||||
labelPlacement="start"
|
||||
control={<Checkbox checked={hideStats} onChange={handleHideStats} />}
|
||||
sx={{
|
||||
margin: "auto 0",
|
||||
'& > .MuiCheckbox-root': {
|
||||
padding: 0
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</>);
|
||||
|
||||
return (<ThemeProvider theme={theme}>
|
||||
<Paper square sx={{
|
||||
minHeight: "100vh", height: "100%",
|
||||
padding: theme.spacing(1),
|
||||
// backgroundColor: "hsl(0deg 0% 97%)"
|
||||
}}>
|
||||
<Search {...({ setContent, setInfo })} />
|
||||
<AppBar color="inherit" sx={{ paddingLeft: 0 }} >
|
||||
{isSmall ? (<>
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
width: 'fit-content',
|
||||
flexWrap: 'wrap',
|
||||
rowGap: theme.spacing(1),
|
||||
columnGap: theme.spacing(1),
|
||||
paddingBottom: theme.spacing(1),
|
||||
alignItems: "center"
|
||||
}}>
|
||||
<NavMenu />
|
||||
<TopMenu />
|
||||
</Box>
|
||||
</>): (<>
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="flex-start"
|
||||
>
|
||||
<NavMenu />
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
width: 'fit-content',
|
||||
flexWrap: 'wrap',
|
||||
alignItems: "center",
|
||||
rowGap: theme.spacing(1),
|
||||
columnGap: theme.spacing(1),
|
||||
paddingTop: theme.spacing(2),
|
||||
paddingBottom: theme.spacing(1),
|
||||
}}>
|
||||
<TopMenu />
|
||||
</Box>
|
||||
</Stack>
|
||||
</>)}
|
||||
</AppBar>
|
||||
<Box sx={{
|
||||
["@media (min-width:917px)"]: { height: "58px" },
|
||||
["@media (max-width:917px)"]: { height: "98px" },
|
||||
["@media (max-width:612px)"]: { height: "132px" },
|
||||
["@media (max-width:600px)"]: { height: "152px" }
|
||||
}}/>
|
||||
{info.text ? (
|
||||
<Typography style={{ textAlign: 'left' }}>{info.text}</Typography>
|
||||
) : (
|
||||
<CardList
|
||||
cards={content.slice(n * (p-1), n * p)}
|
||||
extend={handleExtendSingle}
|
||||
{...({ selected, ext, stats, hideStats })}
|
||||
/>
|
||||
)}
|
||||
</Paper>
|
||||
</ThemeProvider>);
|
||||
}
|
||||
|
||||
type listProps = Omit<chaoticCardProps<ChaoticCard>, "card"> & {
|
||||
cards: ChaoticCard[]
|
||||
selected: ChaoticCard | null
|
||||
}
|
||||
|
||||
const CardList = ({ cards, selected, ext, ...props }: listProps) => {
|
||||
const isSelected = (card: ChaoticCard) => {
|
||||
return (selected && card.gsx$name === selected.gsx$name && card.gsx$set === selected.gsx$set);
|
||||
};
|
||||
|
||||
const list = cards.map((card, i) => {
|
||||
switch (card.gsx$type) {
|
||||
case "Attacks":
|
||||
return (<AttackCard key={card.gsx$name+card.gsx$set}
|
||||
card={card as Attack}
|
||||
ext={(isSelected(card) || ext)}
|
||||
{...props}
|
||||
/>);
|
||||
case "Battlegear":
|
||||
return (<BattlegearCard key={card.gsx$name+card.gsx$set}
|
||||
card={card as Battlegear}
|
||||
ext={(isSelected(card) || ext)}
|
||||
{...props}
|
||||
/>);
|
||||
case "Creatures":
|
||||
return (<CreatureCard key={card.gsx$name+card.gsx$set}
|
||||
card={card as Creature}
|
||||
ext={(isSelected(card) || ext)}
|
||||
{...props}
|
||||
/>);
|
||||
case "Locations":
|
||||
return (<LocationCard key={card.gsx$name+card.gsx$set}
|
||||
card={card as Location}
|
||||
ext={(isSelected(card) || ext)}
|
||||
{...props}
|
||||
/>);
|
||||
case "Mugic":
|
||||
return (<MugicCard key={card.gsx$name+card.gsx$set}
|
||||
card={card as Mugic}
|
||||
ext={(isSelected(card) || ext)}
|
||||
{...props}
|
||||
/>);
|
||||
default:
|
||||
return (<Card key={i}><Typography>Invalid Card Type</Typography></Card>);
|
||||
}
|
||||
});
|
||||
|
||||
// Limitation of typescript - error TS2605
|
||||
return <>{list}</>;
|
||||
};
|
||||
65
src/components/app.js
Normal file
65
src/components/app.js
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { Route, Switch, Redirect } from 'react-router-dom';
|
||||
import loadable from '@loadable/component';
|
||||
|
||||
import useCheckMobileScreen from './_hooks/useCheckMobileScreen';
|
||||
import { PageNotFound, UnderConstruction, Loading } from './Snippets';
|
||||
import Create from './create';
|
||||
import Base from './BaseStylesWrapper';
|
||||
|
||||
const EnterTheCode = loadable(
|
||||
() => import('./entercode'),
|
||||
{ fallback: <Loading /> }
|
||||
);
|
||||
|
||||
const Home = loadable(
|
||||
() => import('./home'),
|
||||
{ fallback: <Loading /> }
|
||||
);
|
||||
|
||||
const Portal = loadable(
|
||||
() => import('./portal'),
|
||||
{ fallback: <Loading /> }
|
||||
);
|
||||
|
||||
const Collection = loadable(
|
||||
() => import('./collection'),
|
||||
{ fallback: <Loading /> }
|
||||
);
|
||||
|
||||
const MobileCollection = loadable(
|
||||
() => import('./_mobile/collection')
|
||||
);
|
||||
|
||||
export default function App() {
|
||||
const isMobile = useCheckMobileScreen();
|
||||
|
||||
useEffect(() => {
|
||||
if (isMobile) {
|
||||
document.styleSheets[0].disabled = true;
|
||||
} else {
|
||||
document.styleSheets[0].disabled = false;
|
||||
}
|
||||
}, [isMobile]);
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route path="/beta/collection" component={Collection} />
|
||||
<Route path="/beta">
|
||||
{({ location }) => <Redirect to={location.pathname.replace("/beta", "")} /> }
|
||||
</Route>
|
||||
{isMobile && <Route path="/collection" component={MobileCollection} />}
|
||||
{/* Normal Routes */}
|
||||
<Base>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route path="/PageNotFound" component={PageNotFound} />
|
||||
<Route path="/UnderConstruction" component={UnderConstruction} />
|
||||
<Route path="/EnterTheCode" component={EnterTheCode} />
|
||||
<Route path="/create" component={Create} />
|
||||
<Route path="/collection" component={Collection} />
|
||||
<Route path="/portal" component={Portal} />
|
||||
</Base>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import API from '../../SpreadsheetData';
|
||||
import { observer, inject } from 'mobx-react';
|
||||
import { FlavorText, Rarity, Unique, Name, Element, Ability, AttackIcon } from '../../Snippets';
|
||||
import { FlavorText, Rarity, Unique, Name, ElementIcon, Ability, AttackIcon } from '../../Snippets';
|
||||
|
||||
@inject((stores, props, context) => props) @observer
|
||||
export default class Attack extends React.Component {
|
||||
|
|
@ -14,14 +14,14 @@ export default class Attack extends React.Component {
|
|||
<img className="thumb" src={API.base_image + (card.gsx$thumb||API.thumb_missing)} onClick={() => this.props.setImage(API.cardImage(card))} />
|
||||
<div className="left">
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} /><br />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} />
|
||||
<span><AttackIcon bp={card.gsx$bp} /> Attack - {card.gsx$bp}</span><br />
|
||||
<div>
|
||||
<span className="bp bigger" >{card.gsx$base}</span> |
|
||||
<Element element="fire" value={card.gsx$fire} />{card.gsx$fire}
|
||||
<Element element="air" value={card.gsx$air} />{card.gsx$air}
|
||||
<Element element="earth" value={card.gsx$earth} />{card.gsx$earth}
|
||||
<Element element="water" value={card.gsx$water} />{card.gsx$water}
|
||||
<ElementIcon element="fire" value={card.gsx$fire} />{card.gsx$fire}
|
||||
<ElementIcon element="air" value={card.gsx$air} />{card.gsx$air}
|
||||
<ElementIcon element="earth" value={card.gsx$earth} />{card.gsx$earth}
|
||||
<ElementIcon element="water" value={card.gsx$water} />{card.gsx$water}
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
|
|
@ -37,6 +37,7 @@ export default class Attack extends React.Component {
|
|||
<div className="fullcard"><img src={API.cardImage(card)} /></div>
|
||||
<div className="right">
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} id={card.gsx$id} />
|
||||
<Ability ability={card.gsx$ability} />
|
||||
<Unique data={{ unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }} />
|
||||
<FlavorText flavortext={card.gsx$flavortext} />
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export default class Battlegear extends React.Component {
|
|||
<img className="thumb" style={{ float: 'left' }} src={API.base_image + (card.gsx$thumb||API.thumb_missing)} onClick={() => this.props.setImage(API.cardImage(card))} />
|
||||
<div className="left">
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} /><br />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} />
|
||||
<span><BattlegearIcon /> Battlegear{card.gsx$types.length > 0 ? " - " + card.gsx$types : null}</span>
|
||||
</div>
|
||||
<div className="right" >
|
||||
|
|
@ -29,6 +29,7 @@ export default class Battlegear extends React.Component {
|
|||
<div className="fullcard"><img src={API.cardImage(card)} /></div>
|
||||
<div className="right" >
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} id={card.gsx$id} />
|
||||
<Ability ability={card.gsx$ability} />
|
||||
<Unique data={{ unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }} />
|
||||
<FlavorText flavortext={card.gsx$flavortext} />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import API from '../../SpreadsheetData';
|
||||
import { observer, inject } from 'mobx-react';
|
||||
import { FlavorText, Rarity, Unique, Name, Element, Mugic, Discipline, Ability, Tribe } from '../../Snippets';
|
||||
import { FlavorText, Rarity, Unique, Name, ElementIcon, MugicIcon, DisciplineIcon, Ability, TribeIcon } from '../../Snippets';
|
||||
|
||||
@inject((stores, props, context) => props) @observer
|
||||
export default class Creature extends React.Component {
|
||||
|
|
@ -11,7 +11,7 @@ export default class Creature extends React.Component {
|
|||
|
||||
const mugic = [];
|
||||
for (let i = 0; i < card.gsx$mugicability; i++) {
|
||||
mugic.push(<Mugic key={i} tribe={card.gsx$tribe} />);
|
||||
mugic.push(<MugicIcon key={i} tribe={card.gsx$tribe} />);
|
||||
}
|
||||
|
||||
const TribeLine = () => {
|
||||
|
|
@ -25,7 +25,7 @@ export default class Creature extends React.Component {
|
|||
}
|
||||
const line = " " + (past ? "Past " : "") + types;
|
||||
|
||||
return <span><Tribe tribe={card.gsx$tribe} />{line}</span>;
|
||||
return <span><TribeIcon tribe={card.gsx$tribe} />{line}</span>;
|
||||
};
|
||||
|
||||
const stat_range = (stat, name) => {
|
||||
|
|
@ -42,20 +42,18 @@ export default class Creature extends React.Component {
|
|||
return Number(energy);
|
||||
};
|
||||
|
||||
console.log(this.props);
|
||||
|
||||
if (this.props.ext == false) return (
|
||||
<div className="card creature">
|
||||
<img className="thumb" style={{ float: 'left' }} src={API.base_image + (card.gsx$thumb||API.thumb_missing)} onClick={() => this.props.setImage(API.cardImage(card))} />
|
||||
<div className="left">
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} /><br />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} />
|
||||
<TribeLine /><br />
|
||||
<div>
|
||||
<Element element="fire" value={card.gsx$elements.toLowerCase().indexOf("fire") >=0} />
|
||||
<Element element="air" value={card.gsx$elements.toLowerCase().indexOf("air") >=0} />
|
||||
<Element element="earth" value={card.gsx$elements.toLowerCase().indexOf("earth") >=0} />
|
||||
<Element element="water" value={card.gsx$elements.toLowerCase().indexOf("water") >=0} />
|
||||
<ElementIcon element="fire" value={card.gsx$elements.toLowerCase().indexOf("fire") >=0} />
|
||||
<ElementIcon element="air" value={card.gsx$elements.toLowerCase().indexOf("air") >=0} />
|
||||
<ElementIcon element="earth" value={card.gsx$elements.toLowerCase().indexOf("earth") >=0} />
|
||||
<ElementIcon element="water" value={card.gsx$elements.toLowerCase().indexOf("water") >=0} />
|
||||
</div>
|
||||
<span>{mugic}</span>
|
||||
</div>
|
||||
|
|
@ -78,16 +76,16 @@ export default class Creature extends React.Component {
|
|||
<br />
|
||||
<div className="stats">
|
||||
<div className="energy">
|
||||
{stat_range(card.gsx$courage, card.gsx$name)}<Discipline discipline="courage" />
|
||||
{stat_range(card.gsx$courage, card.gsx$name)}<DisciplineIcon discipline="courage" />
|
||||
</div>
|
||||
<div className="energy">
|
||||
{stat_range(card.gsx$power, card.gsx$name)}<Discipline discipline="power" />
|
||||
{stat_range(card.gsx$power, card.gsx$name)}<DisciplineIcon discipline="power" />
|
||||
</div>
|
||||
<div className="energy">
|
||||
{stat_range(card.gsx$wisdom, card.gsx$name)}<Discipline discipline="wisdom" />
|
||||
{stat_range(card.gsx$wisdom, card.gsx$name)}<DisciplineIcon discipline="wisdom" />
|
||||
</div>
|
||||
<div className="energy">
|
||||
{stat_range(card.gsx$speed, card.gsx$name)}<Discipline discipline="speed" />
|
||||
{stat_range(card.gsx$speed, card.gsx$name)}<DisciplineIcon discipline="speed" />
|
||||
</div>
|
||||
<div className="energy" style={{ fontWeight: 'bold' }}>{energy_range(card.gsx$energy, card.gsx$name)}
|
||||
</div>
|
||||
|
|
@ -113,10 +111,11 @@ export default class Creature extends React.Component {
|
|||
</div>
|
||||
<div className="right" >
|
||||
<Name name={card.gsx$name} />
|
||||
<span>{stat_range(card.gsx$courage, card.gsx$name)} <Discipline discipline="courage" /></span>
|
||||
<span>{stat_range(card.gsx$power, card.gsx$name)} <Discipline discipline="power" /></span>
|
||||
<span>{stat_range(card.gsx$wisdom, card.gsx$name)} <Discipline discipline="wisdom" /></span>
|
||||
<span>{stat_range(card.gsx$speed, card.gsx$name)} <Discipline discipline="speed" /></span>
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} id={card.gsx$id} />
|
||||
<span>{stat_range(card.gsx$courage, card.gsx$name)} <DisciplineIcon discipline="courage" /></span>
|
||||
<span>{stat_range(card.gsx$power, card.gsx$name)} <DisciplineIcon discipline="power" /></span>
|
||||
<span>{stat_range(card.gsx$wisdom, card.gsx$name)} <DisciplineIcon discipline="wisdom" /></span>
|
||||
<span>{stat_range(card.gsx$speed, card.gsx$name)} <DisciplineIcon discipline="speed" /></span>
|
||||
<span style={{ fontWeight: 'bold' }}>{energy_range(card.gsx$energy, card.gsx$name)}</span>
|
||||
<br />
|
||||
<Ability ability={card.gsx$ability} tribe={card.gsx$tribe} />
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export default class Location extends React.Component {
|
|||
<img className="thumb" style={{ float: 'left', width: '100px', height: '98px' }} src={API.base_image + (card.gsx$thumb||API.thumb_missing)} onClick={() => this.props.setImage(API.cardImage(card))} />
|
||||
<div className="left">
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} /><br />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} />
|
||||
<span><LocationIcon /> Location{card.gsx$types.length > 0 ? " - " + card.gsx$types : null}</span><br />
|
||||
<Initiative initiative={card.gsx$initiative} />
|
||||
</div>
|
||||
|
|
@ -31,6 +31,7 @@ export default class Location extends React.Component {
|
|||
<div className="fullcard"><img src={API.cardImage(card)} /></div>
|
||||
<div className="right">
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} id={card.gsx$id} />
|
||||
<Initiative initiative={card.gsx$initiative} />
|
||||
<Ability ability={card.gsx$ability} />
|
||||
<Unique data={{ unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }} />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import API from '../../SpreadsheetData';
|
||||
import { observer, inject } from 'mobx-react';
|
||||
import { FlavorText, Rarity, Unique, Name, Mugic as MugicCounter, Ability, Tribe } from '../../Snippets';
|
||||
import { FlavorText, Rarity, Unique, Name, MugicIcon as MugicCounter, Ability, TribeIcon } from '../../Snippets';
|
||||
import MugicPlay from '../../mugicplayer/playbutton.tsx';
|
||||
|
||||
@inject((stores, props, context) => props) @observer
|
||||
|
|
@ -33,8 +33,8 @@ export default class Mugic extends React.Component {
|
|||
<img className="thumb" style={{ float: 'left' }} src={API.base_image + (card.gsx$thumb||API.thumb_missing)} onClick={() => this.props.setImage(API.cardImage(card))} />
|
||||
<div className="left">
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} /> <br />
|
||||
<Tribe size="icon16" tribe={card.gsx$tribe} /> Mugic - {card.gsx$tribe}<br />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} />
|
||||
<TribeIcon size="icon16" tribe={card.gsx$tribe} /> Mugic - {card.gsx$tribe}<br />
|
||||
<span>{mugicCounters}</span><MugicPlay notes={card.gsx$shownotes?.length > 0 ? card.gsx$shownotes : card.gsx$notes}/><br />
|
||||
</div>
|
||||
<br />
|
||||
|
|
@ -50,6 +50,7 @@ export default class Mugic extends React.Component {
|
|||
<div className="fullcard"><img src={API.cardImage(card)} /></div>
|
||||
<div className="right" >
|
||||
<Name name={card.gsx$name} />
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} id={card.gsx$id} />
|
||||
<Ability ability={card.gsx$ability} tribe={card.gsx$tribe} />
|
||||
<Unique data={{ unique: card.gsx$unique, loyal: card.gsx$loyal, legendary: card.gsx$legendary }} />
|
||||
<FlavorText flavortext={card.gsx$flavortext} />
|
||||
|
|
|
|||
|
|
@ -6,28 +6,30 @@ export interface BaseCard {
|
|||
gsx$type: CardType
|
||||
gsx$set: string
|
||||
gsx$rarity: string
|
||||
gsx$id: string
|
||||
gsx$image: string
|
||||
gsx$thumb: string
|
||||
gsx$ability: string
|
||||
gsx$flavortext: string
|
||||
gsx$splash: string
|
||||
gsx$types: string
|
||||
gsx$unique: number | string
|
||||
gsx$legendary: number | string
|
||||
gsx$loyal: number | string
|
||||
gsx$unique: string
|
||||
gsx$legendary: string
|
||||
gsx$loyal: string
|
||||
gsx$alt?: string
|
||||
gsx$alt2?: string
|
||||
gsx$ic?: string // imgur card
|
||||
gsx$if?: string // imgur fullart
|
||||
gsx$artist?: string
|
||||
}
|
||||
|
||||
export interface Attack extends BaseCard {
|
||||
gsx$fire: number | string
|
||||
gsx$air: number | string
|
||||
gsx$earth: number | string
|
||||
gsx$water: number | string
|
||||
gsx$base: number | string
|
||||
gsx$bp: number | string
|
||||
gsx$fire: string
|
||||
gsx$air: string
|
||||
gsx$earth: string
|
||||
gsx$water: string
|
||||
gsx$base: string
|
||||
gsx$bp: string
|
||||
}
|
||||
|
||||
export interface Battlegear extends BaseCard {
|
||||
|
|
@ -36,14 +38,14 @@ export interface Battlegear extends BaseCard {
|
|||
|
||||
export interface Creature extends BaseCard {
|
||||
gsx$tribe: string
|
||||
gsx$courage: string | number
|
||||
gsx$power: string | number
|
||||
gsx$wisdom: string | number
|
||||
gsx$speed: string | number
|
||||
gsx$energy: string | number
|
||||
gsx$courage: string
|
||||
gsx$power: string
|
||||
gsx$wisdom: string
|
||||
gsx$speed: string
|
||||
gsx$energy: string
|
||||
gsx$elements: string
|
||||
gsx$brainwashed: string
|
||||
gsx$mugicability: string | number
|
||||
gsx$mugicability: string
|
||||
gsx$avatar?: string
|
||||
gsx$subtype: string
|
||||
gsx$ia?: string // imgur avatar
|
||||
|
|
@ -56,7 +58,9 @@ export interface Location extends BaseCard {
|
|||
|
||||
export interface Mugic extends BaseCard {
|
||||
gsx$tribe: string
|
||||
gsx$cost: number | string
|
||||
gsx$cost: string
|
||||
gsx$notes: string
|
||||
gsx$shownotes: string
|
||||
}
|
||||
|
||||
export type Card = Attack | Battlegear | Creature | Location | Mugic;
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ export default function PackSimulator () {
|
|||
})
|
||||
.catch(() => {});
|
||||
|
||||
const cards = [];
|
||||
const cards: JSX.Element[] = [];
|
||||
for (let i = 0; i < 9; i++) {
|
||||
cards.push(blankCard(i));
|
||||
}
|
||||
setCards(cards);
|
||||
|
||||
const setsInput = [];
|
||||
const setsInput: JSX.Element[] = [];
|
||||
let i = 1;
|
||||
for (const set in API.sets) {
|
||||
setsInput.push(<option key={i++} value={set}>{API.sets[set]}</option>);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import API from '../../SpreadsheetData';
|
|||
import s from '../../../styles/app.style';
|
||||
import { observer, inject } from 'mobx-react';
|
||||
import Single from './_base';
|
||||
import { PageNotFound, Element, Mugic, Discipline, Tribe } from '../../Snippets';
|
||||
import { PageNotFound, ElementIcon, MugicIcon, DisciplineIcon, TribeIcon } from '../../Snippets';
|
||||
|
||||
function Artist(props) {
|
||||
const artists = [];
|
||||
|
|
@ -40,7 +40,7 @@ export default class SingleCreature extends React.Component {
|
|||
|
||||
const mugic = [];
|
||||
for (let i = 0; i < parseInt(card_data.gsx$mugicability || 0); i++) {
|
||||
mugic.push(<Mugic key={i} tribe={tribe} />);
|
||||
mugic.push(<MugicIcon key={i} tribe={tribe} />);
|
||||
}
|
||||
|
||||
const col2 = [];
|
||||
|
|
@ -78,16 +78,16 @@ export default class SingleCreature extends React.Component {
|
|||
col0={<>
|
||||
<div>
|
||||
<strong>Tribe: </strong>
|
||||
<Tribe tribe={tribe} />
|
||||
<TribeIcon tribe={tribe} />
|
||||
{tribe}
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<strong>Disciplines: </strong>
|
||||
{card_data.gsx$courage}<Discipline discipline="courage" />
|
||||
{card_data.gsx$power}<Discipline discipline="power" />
|
||||
{card_data.gsx$wisdom}<Discipline discipline="wisdom" />
|
||||
{card_data.gsx$speed}<Discipline discipline="speed" />
|
||||
{card_data.gsx$courage}<DisciplineIcon discipline="courage" />
|
||||
{card_data.gsx$power}<DisciplineIcon discipline="power" />
|
||||
{card_data.gsx$wisdom}<DisciplineIcon discipline="wisdom" />
|
||||
{card_data.gsx$speed}<DisciplineIcon discipline="speed" />
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
|
|
@ -97,10 +97,10 @@ export default class SingleCreature extends React.Component {
|
|||
<hr />
|
||||
<div>
|
||||
<strong>Elements: </strong>
|
||||
<Element element="fire" value={card_data.gsx$elements.toLowerCase().indexOf("fire") >=0} />
|
||||
<Element element="air" value={card_data.gsx$elements.toLowerCase().indexOf("air") >=0} />
|
||||
<Element element="earth" value={card_data.gsx$elements.toLowerCase().indexOf("earth") >=0} />
|
||||
<Element element="water" value={card_data.gsx$elements.toLowerCase().indexOf("water") >=0} />
|
||||
<ElementIcon element="fire" value={card_data.gsx$elements.toLowerCase().indexOf("fire") >=0} />
|
||||
<ElementIcon element="air" value={card_data.gsx$elements.toLowerCase().indexOf("air") >=0} />
|
||||
<ElementIcon element="earth" value={card_data.gsx$elements.toLowerCase().indexOf("earth") >=0} />
|
||||
<ElementIcon element="water" value={card_data.gsx$elements.toLowerCase().indexOf("water") >=0} />
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
|
|
@ -127,7 +127,7 @@ export default class SingleCreature extends React.Component {
|
|||
|
||||
const mugic = [];
|
||||
for (let i = 0; i < parseInt(card_data.gsx$mugicability || 0); i++) {
|
||||
mugic.push(<Mugic key={i} tribe={tribe} />);
|
||||
mugic.push(<MugicIcon key={i} tribe={tribe} />);
|
||||
}
|
||||
|
||||
return (<Single
|
||||
|
|
@ -135,20 +135,20 @@ export default class SingleCreature extends React.Component {
|
|||
col0={<>
|
||||
<div>
|
||||
<strong>Tribe: </strong>
|
||||
<Tribe tribe={tribe} />
|
||||
<TribeIcon tribe={tribe} />
|
||||
{tribe}
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<strong>Disciplines: </strong>
|
||||
{card_data.gsx$courage}
|
||||
<Discipline discipline="courage" />
|
||||
<DisciplineIcon discipline="courage" />
|
||||
{card_data.gsx$power}
|
||||
<Discipline discipline="power" />
|
||||
<DisciplineIcon discipline="power" />
|
||||
{card_data.gsx$speed}
|
||||
<Discipline discipline="speed" />
|
||||
<DisciplineIcon discipline="speed" />
|
||||
{card_data.gsx$wisdom}
|
||||
<Discipline discipline="wisdom" />
|
||||
<DisciplineIcon discipline="wisdom" />
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
|
|
@ -158,10 +158,10 @@ export default class SingleCreature extends React.Component {
|
|||
<hr />
|
||||
<div>
|
||||
<strong>Elements: </strong>
|
||||
<Element element="fire" value={card_data.gsx$elements.toLowerCase().indexOf("fire") >=0} />
|
||||
<Element element="air" value={card_data.gsx$elements.toLowerCase().indexOf("air") >=0} />
|
||||
<Element element="earth" value={card_data.gsx$elements.toLowerCase().indexOf("earth") >=0} />
|
||||
<Element element="water" value={card_data.gsx$elements.toLowerCase().indexOf("water") >=0} />
|
||||
<ElementIcon element="fire" value={card_data.gsx$elements.toLowerCase().indexOf("fire") >=0} />
|
||||
<ElementIcon element="air" value={card_data.gsx$elements.toLowerCase().indexOf("air") >=0} />
|
||||
<ElementIcon element="earth" value={card_data.gsx$elements.toLowerCase().indexOf("earth") >=0} />
|
||||
<ElementIcon element="water" value={card_data.gsx$elements.toLowerCase().indexOf("water") >=0} />
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import API from '../../SpreadsheetData';
|
|||
import s from '../../../styles/app.style';
|
||||
import { observer, inject } from 'mobx-react';
|
||||
import Single from './_base';
|
||||
import { PageNotFound, Mugic, Tribe } from '../../Snippets';
|
||||
import { PageNotFound, MugicIcon, TribeIcon } from '../../Snippets';
|
||||
|
||||
@inject((stores, props, context) => props) @observer
|
||||
export default class SingleMugic extends React.Component {
|
||||
|
|
@ -35,7 +35,7 @@ export default class SingleMugic extends React.Component {
|
|||
}
|
||||
else {
|
||||
for (let i = 0; i < parseInt(card_data.gsx$cost); i++) {
|
||||
cost.push(<Mugic tribe={tribe} key={i} />);
|
||||
cost.push(<MugicIcon tribe={tribe} key={i} />);
|
||||
}
|
||||
}
|
||||
return cost;
|
||||
|
|
@ -49,7 +49,7 @@ export default class SingleMugic extends React.Component {
|
|||
col0={<>
|
||||
<div>
|
||||
<strong>Tribe: </strong>
|
||||
<Tribe tribe={tribe} />
|
||||
<TribeIcon tribe={tribe} />
|
||||
{tribe}
|
||||
</div>
|
||||
{card_data.gsx$cost !== "" && (<>
|
||||
|
|
@ -86,7 +86,7 @@ export default class SingleMugic extends React.Component {
|
|||
col0={<>
|
||||
<div>
|
||||
<strong>Tribe: </strong>
|
||||
<Tribe tribe={tribe} />
|
||||
<TribeIcon tribe={tribe} />
|
||||
{tribe}
|
||||
</div>
|
||||
{card_data.gsx$cost !== "" && (<>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { observable } from "mobx";
|
|||
import { observer, inject } from 'mobx-react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import API from '../../SpreadsheetData';
|
||||
import { Rarity, Ability } from '../../Snippets';
|
||||
import { RarityIcon, Ability } from '../../Snippets';
|
||||
import s from '../../../styles/app.style';
|
||||
|
||||
// own "name" display function
|
||||
|
|
@ -74,7 +74,7 @@ export default class Single extends React.Component {
|
|||
{card.gsx$rarity && (<>
|
||||
<div>
|
||||
<strong>Rarity: </strong>
|
||||
<Rarity set={card.gsx$set} rarity={card.gsx$rarity} iconOnly />
|
||||
<RarityIcon set={card.gsx$set} rarity={card.gsx$rarity} iconOnly />
|
||||
{card.gsx$rarity}
|
||||
</div>
|
||||
<hr />
|
||||
|
|
|
|||
195
src/index.js
195
src/index.js
|
|
@ -1,190 +1,13 @@
|
|||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import { BrowserRouter as Router, Link, Route, Switch, Redirect } from 'react-router-dom';
|
||||
import loadable from '@loadable/component';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import App from './components/app';
|
||||
|
||||
/* Components */
|
||||
import API from './components/SpreadsheetData';
|
||||
import { PageNotFound, UnderConstruction, Donate, Loading } from './components/Snippets';
|
||||
import Create from './components/create/index';
|
||||
const rootElement = document.getElementById('root');
|
||||
|
||||
const EnterTheCode = loadable(
|
||||
() => import('./components/entercode'),
|
||||
{ fallback: <Loading /> }
|
||||
);
|
||||
|
||||
const Home = loadable(
|
||||
() => import('./components/home'),
|
||||
{ fallback: <Loading /> }
|
||||
);
|
||||
|
||||
const Portal = loadable(
|
||||
() => import('./components/portal'),
|
||||
{ fallback: <Loading /> }
|
||||
);
|
||||
|
||||
const Collection = loadable(
|
||||
() => import('./components/collection'),
|
||||
{ fallback: <Loading /> }
|
||||
);
|
||||
|
||||
/**
|
||||
* This function is to define beta routes
|
||||
*/
|
||||
function BetaRoutingWrapper() {
|
||||
return (
|
||||
<Switch>
|
||||
<Route path="/beta/collection" component={Collection} />
|
||||
<Route path="/beta">
|
||||
{({ location }) => <Redirect to={location.pathname.replace("/beta", "")} /> }
|
||||
</Route>
|
||||
<Route component={Routing} />
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
|
||||
function Routing() {
|
||||
return (
|
||||
<Switch>
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route path="/PageNotFound" component={PageNotFound} />
|
||||
<Route path="/UnderConstruction" component={UnderConstruction} />
|
||||
<Route path="/EnterTheCode" component={EnterTheCode} />
|
||||
<Route path="/create" component={Create} />
|
||||
<Route path="/collection" component={Collection} />
|
||||
<Route path="/portal" component={Portal} />
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
|
||||
function Base(props) {
|
||||
// Configuration for the language and background
|
||||
// Images managed in css file
|
||||
const language = "ENG";
|
||||
const bkgrnd = "05";
|
||||
|
||||
const children = <BetaRoutingWrapper />;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="fix-pgBkgrnd-repeat-x">
|
||||
<div className={"fix-img-bkgrnd fix-img-bkgrnd_"+bkgrnd}></div>
|
||||
</div>
|
||||
<div className="pgBkgrnd-repeat-x">
|
||||
<div className="img-bkgrnd">
|
||||
<div className="content-wrap">
|
||||
<div className="legacy legacy-header">
|
||||
<div className="header">
|
||||
<div id="nav">
|
||||
<div className="zero-clear-line headerSpriteNav-wrap">
|
||||
<ul id="unity-sprite" className={language}>
|
||||
<li id="unity-nav1" className={language}></li>
|
||||
<li id="unity-nav2" className={language}><Link to={`/collection/`}><span>Collect</span></Link></li>
|
||||
<li id="unity-nav3" className={language}><a href="https://chaoticbackup.forumotion.com/f11-deck-building"><span>Build</span></a></li>
|
||||
<li id="unity-nav4" className={language}><a href="https://chaoticbackup.forumotion.com/f16-trading-buying-and-selling"><span>Trade</span></a></li>
|
||||
<li id="unity-nav5" className={language}><Link to={`/`}><span>Home</span></Link></li>
|
||||
<li id="unity-nav6" className={language}><a href="https://chaoticbackup.forumotion.com"><span>Forums</span></a></li>
|
||||
<li id="unity-nav7" className={language}><Link to={`/portal/`}><span>Portal</span></Link></li>
|
||||
<li id="unity-nav8" className={language}><a href="https://chaoticrecode.com"><span>Play</span></a></li>
|
||||
<li id="unity-nav9" className={language}></li>
|
||||
</ul>
|
||||
<ul id="unityETC-sprite" className={language}>
|
||||
<li id="unity-nav10" className={language}><Link to={`/EnterTheCode`}><span>Enter the Code</span></Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="banner-ad-top">
|
||||
</div>
|
||||
<div className="legacy content">
|
||||
<div className="left-column">
|
||||
<div className="full-width clear-line" style={{ marginBottom: "5px" }}>
|
||||
</div>
|
||||
</div>
|
||||
<div className="full-column">
|
||||
<div className="pods-wrap pad5px-btm">
|
||||
<div className="clear-line full-width">
|
||||
<div className="adPod-top-wrap">
|
||||
<div className="videoAdPod-topleft">
|
||||
<div className="videoAdPod-topLeft-repeat-x"></div>
|
||||
</div>
|
||||
<div className="videoAdPod-topright">
|
||||
<div className="videoAdPod-topRight-repeat-x"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-area-repeat-xy">
|
||||
<div className="content-area-top-repeat-x">
|
||||
<div className="content-area-left-repeat-y">
|
||||
<div className="content-area-right-repeat-y">
|
||||
<div className="content-area-inner-space">
|
||||
<div id="player">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-btm-wrap">
|
||||
<div className="content-area-btm-left">
|
||||
<div className="content-left-btm-repeat-x">
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-area-btm-right">
|
||||
<div className="content-right-btm-repeat-x">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="right-column">
|
||||
<div className="full-width clear-line" style={{ marginBottom: "5px" }}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="banner-ad-bottom">
|
||||
</div>
|
||||
<div className="legacy legacy-footer">
|
||||
<div className="footer-wrap">
|
||||
<div className="footer-repeat-x">
|
||||
<div className="footer-left">
|
||||
<div className="footer-right">
|
||||
<div className="footer-text">
|
||||
<div className="footer-search">
|
||||
<br /><br />
|
||||
<Donate />
|
||||
</div>
|
||||
<div className="footer-nav">
|
||||
<div className="copyright">
|
||||
©2008 Chaotic USA Entertainment Group, Inc.
|
||||
<br />
|
||||
U.S. Pat 5810666 and 5954332 and other pending patent applications. All Rights Reserved.
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer-language">
|
||||
<a href='#' onClick={(e) => {e.stopPropagation(); e.preventDefault(); API.purgeDB()}} className="page-options" title="Change Language">
|
||||
<img src="/public/img/flag_usa_.gif" alt="English (Change Language)" width="40" height="27"/>
|
||||
<br />English (Change Language)
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
render(
|
||||
<Router>
|
||||
<Base path="/*" href="/" />
|
||||
</Router>
|
||||
, document.getElementById('root'),
|
||||
ReactDOM.render(
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>,
|
||||
rootElement
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@
|
|||
// Process & infer types from .js files.
|
||||
"allowJs": true,
|
||||
// Support jsx in .tsx files (https://www.typescriptlang.org/docs/handbook/jsx.html)
|
||||
"jsx": "preserve",
|
||||
"jsx": "react",
|
||||
// Specifies module code generation
|
||||
"module": "esnext",
|
||||
// Don't emit; allow Babel to transform files.
|
||||
"noEmit": true,
|
||||
// Enable strictest settings like strictNullChecks & noImplicitAny.
|
||||
// "strict": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitAny": false,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"alwaysStrict": false,
|
||||
|
|
@ -31,7 +33,7 @@
|
|||
"resolveJsonModule": true,
|
||||
// Library files to be used in the project.
|
||||
// Tells the compiler that "DOM-APIs" and new ECMAScript features are valid.
|
||||
"lib": ["dom", "esnext"],
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
// Allows @decorators
|
||||
"experimentalDecorators": true,
|
||||
// List of folders to include type definitions from.
|
||||
|
|
@ -45,11 +47,11 @@
|
|||
"inlineSourceMap": true
|
||||
},
|
||||
"include": [
|
||||
"src/components"
|
||||
"src/components",
|
||||
".eslintrc.js"
|
||||
],
|
||||
"exclude": [
|
||||
"build",
|
||||
"node_modules",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user