mirror of
https://github.com/omg-xtao/gc-tools.git
synced 2024-11-21 06:47:40 +00:00
first
This commit is contained in:
parent
23d6ba1a11
commit
8c8e00b687
2
.gitignore
vendored
2
.gitignore
vendored
@ -11,6 +11,8 @@
|
||||
# production
|
||||
/build
|
||||
|
||||
.idea
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
|
5
.idea/.gitignore
vendored
Normal file
5
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
7
.idea/discord.xml
Normal file
7
.idea/discord.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
</project>
|
12
.idea/gc-tools.iml
Normal file
12
.idea/gc-tools.iml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
6
.idea/inspectionProfiles/Project_Default.xml
Normal file
6
.idea/inspectionProfiles/Project_Default.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/gc-tools.iml" filepath="$PROJECT_DIR$/.idea/gc-tools.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
9
Dockerfile
Normal file
9
Dockerfile
Normal file
@ -0,0 +1,9 @@
|
||||
FROM node:16-slim
|
||||
ADD . /booklist-react
|
||||
WORKDIR /booklist-react
|
||||
RUN npm install
|
||||
RUN npm install -g serve
|
||||
RUN npm run build
|
||||
CMD ["npm","install","-g","serve"]
|
||||
CMD ["serve", "-s", "build"]
|
||||
EXPOSE 3000
|
18
docker-compose.yml
Normal file
18
docker-compose.yml
Normal file
@ -0,0 +1,18 @@
|
||||
version: '3.8'
|
||||
services:
|
||||
exzork_booklist_react:
|
||||
container_name: exzork_booklist_react
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- .:/booklist-react
|
||||
- /booklist-react/node_modules
|
||||
- /booklist-react/build
|
||||
environment:
|
||||
- VIRTUAL_HOST=booklist-react.exzork.me
|
||||
- LETSENCRYPT_HOST=booklist-react.exzork.me
|
||||
- LETSENCRYPT_EMAIL=muhammadeko.if@gmail.com
|
||||
networks:
|
||||
default :
|
||||
name: nginx-proxy
|
888
package-lock.json
generated
888
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
15
package.json
15
package.json
@ -3,6 +3,10 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.9.0",
|
||||
"@emotion/styled": "^11.8.1",
|
||||
"@mui/material": "^5.6.3",
|
||||
"@tailwindcss/forms": "^0.5.0",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/react": "^13.1.1",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
@ -10,9 +14,17 @@
|
||||
"@types/node": "^16.11.32",
|
||||
"@types/react": "^18.0.8",
|
||||
"@types/react-dom": "^18.0.3",
|
||||
"autoprefixer": "^10.4.5",
|
||||
"axios": "^0.27.2",
|
||||
"fs": "^0.0.1-security",
|
||||
"lodash": "^4.17.21",
|
||||
"postcss": "^8.4.12",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-select-search": "^3.0.9",
|
||||
"tailwindcss": "^3.0.24",
|
||||
"typescript": "^4.6.4",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
@ -39,5 +51,8 @@
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash": "^4.14.182"
|
||||
}
|
||||
}
|
||||
|
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
62
src/App.tsx
62
src/App.tsx
@ -1,26 +1,46 @@
|
||||
import React from 'react';
|
||||
import React, {Component} from 'react';
|
||||
import logo from './logo.svg';
|
||||
import './App.css';
|
||||
import Main from "./components/Main";
|
||||
import {BrowserRouter} from "react-router-dom";
|
||||
import Navbar from "./components/Navbar";
|
||||
import Header from "./components/Header";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src={logo} className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/App.tsx</code> and save to reload.
|
||||
</p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React
|
||||
</a>
|
||||
</header>
|
||||
</div>
|
||||
);
|
||||
interface IState{
|
||||
headerTitle: string;
|
||||
}
|
||||
|
||||
export default App;
|
||||
export default class App extends Component<{},IState>{
|
||||
constructor(props:{}) {
|
||||
super(props);
|
||||
this.state = {
|
||||
headerTitle: 'Hello World'
|
||||
}
|
||||
}
|
||||
|
||||
handleHeaderTitleChange = (headerTitle:string) =>{
|
||||
this.setState({
|
||||
headerTitle: headerTitle
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const NavbarProps = {
|
||||
headerTitle: this.state.headerTitle,
|
||||
handleHeaderTitleChange: this.handleHeaderTitleChange
|
||||
}
|
||||
const HeaderProps = {
|
||||
name: this.state.headerTitle,
|
||||
}
|
||||
const MainProps = {
|
||||
handleHeaderTitleChange: this.handleHeaderTitleChange
|
||||
}
|
||||
return(
|
||||
<BrowserRouter>
|
||||
<Navbar {...NavbarProps}/>
|
||||
<Header {...HeaderProps}/>
|
||||
<Main {...MainProps}/>
|
||||
</BrowserRouter>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
11
src/components/Header.tsx
Normal file
11
src/components/Header.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import React from "react";
|
||||
|
||||
export default function Header(props:{name:string}){
|
||||
return (
|
||||
<header className="bg-white shadow">
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-xl md:text-3xl font-bold text-gray-900">{props.name}</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
19
src/components/Main.tsx
Normal file
19
src/components/Main.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
import RouteMenu from "./RouteMenu";
|
||||
import {RouteProps} from "react-router-dom";
|
||||
|
||||
interface Props extends RouteProps{
|
||||
handleHeaderTitleChange: (title: string) => void;
|
||||
}
|
||||
export default function Main(props: Props) {
|
||||
const RouteMenuProps = {
|
||||
handleHeaderTitleChange: props.handleHeaderTitleChange
|
||||
};
|
||||
return (
|
||||
<main className="bg-gray-100 min-h-full">
|
||||
<div className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8 ">
|
||||
<RouteMenu {...RouteMenuProps}/>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
25
src/components/MenuDesktop.tsx
Normal file
25
src/components/MenuDesktop.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import React from "react";
|
||||
import {useLocation, Link, useNavigate} from "react-router-dom"
|
||||
export default function MenuDesktop(props:{handleHeaderTitleChange: (title:string) => void}) {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const {handleHeaderTitleChange} = props;
|
||||
|
||||
|
||||
/*
|
||||
{location.pathname === "/" ? (
|
||||
<Link to="/" className="menu-item bg-gray-900 text-white px-3 py-2 rounded-md text-sm font-medium">Home</Link>
|
||||
) : (
|
||||
<Link to="/" onClick={() => handleHeaderTitleChange("Home")} className="menu-item text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Home</Link>
|
||||
)}
|
||||
*/
|
||||
return (
|
||||
<>
|
||||
{location.pathname === "/artifact" ? (
|
||||
<Link to="/artifact" className="menu-item bg-gray-900 text-white px-3 py-2 rounded-md text-sm font-medium">Artifact</Link>
|
||||
) : (
|
||||
<Link to="/artifact" onClick={() => handleHeaderTitleChange("Artifact Command Generator")} className="menu-item text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Artifact</Link>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
25
src/components/MenuMobile.tsx
Normal file
25
src/components/MenuMobile.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import React from "react";
|
||||
import {useLocation, Link} from "react-router-dom";
|
||||
|
||||
export default function MenuMobile(props: any) {
|
||||
const location = useLocation();
|
||||
const {handleHeaderTitleChange} = props;
|
||||
|
||||
/*
|
||||
{location.pathname === "/" ? (
|
||||
<Link to="/" className="menu-item block bg-gray-900 text-white px-3 py-2 rounded-md text-sm font-medium">Home</Link>
|
||||
) : (
|
||||
<Link to="/" onClick={() => handleHeaderTitleChange("Home")} className="menu-item block text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Home</Link>
|
||||
)}
|
||||
*/
|
||||
return (
|
||||
<>
|
||||
|
||||
{location.pathname === "/artifact" ? (
|
||||
<Link to="/artifact" className="menu-item block bg-gray-900 text-white px-3 py-2 rounded-md text-sm font-medium">Artifact</Link>
|
||||
) : (
|
||||
<Link to="/artifact" onClick={() => handleHeaderTitleChange("Artifact Command Generator")} className="menu-item block text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Artifact</Link>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
77
src/components/Navbar.tsx
Normal file
77
src/components/Navbar.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
import React from "react";
|
||||
import MenuDesktop from "./MenuDesktop";
|
||||
import MenuMobile from "./MenuMobile";
|
||||
|
||||
class Navbar extends React.Component {
|
||||
handleHeaderTitleChange;
|
||||
toggleMobileMenu = () => {
|
||||
const menuShow = document.querySelector(".menu-show");
|
||||
const menuHide = document.querySelector(".menu-hide");
|
||||
const mobileMenu = document.querySelector("#mobile-menu");
|
||||
if (mobileMenu && menuHide && menuShow){
|
||||
if (menuShow.classList.contains("block")) {
|
||||
menuShow.classList.remove("block");
|
||||
menuShow.classList.add("hidden");
|
||||
menuHide.classList.remove("hidden");
|
||||
menuHide.classList.add("block");
|
||||
mobileMenu.classList.remove("hidden");
|
||||
} else {
|
||||
menuShow.classList.remove("hidden");
|
||||
menuShow.classList.add("block");
|
||||
menuHide.classList.remove("block");
|
||||
menuHide.classList.add("hidden");
|
||||
mobileMenu.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor(props:{handleHeaderTitleChange: (title:string) => void}) {
|
||||
super(props);
|
||||
const {handleHeaderTitleChange} = props;
|
||||
|
||||
this.handleHeaderTitleChange = handleHeaderTitleChange;
|
||||
const pathname =window.location.pathname;
|
||||
|
||||
if(pathname==="/") handleHeaderTitleChange("Home")
|
||||
else if(pathname==="/artifact") handleHeaderTitleChange("Artifact Command Generator")
|
||||
}
|
||||
|
||||
render() {
|
||||
return(
|
||||
<nav className="bg-gray-800">
|
||||
<div className="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8">
|
||||
<div className="relative flex items-center justify-between h-16">
|
||||
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
|
||||
{/* Mobile menu button */}
|
||||
<button onClick={this.toggleMobileMenu} className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:bg-gray-700 focus:text-white transition duration-150 ease-in-out">
|
||||
<svg className="menu-show block h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h16"/>
|
||||
</svg>
|
||||
<svg className="menu-hide hidden h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex-1 flex items-center justify-center sm:items-stretch sm:justify-start">
|
||||
<div className="flex-shrink-0 flex items-center text-white text-lg">
|
||||
Grasscutter Tools
|
||||
</div>
|
||||
<div className="hidden sm:block sm:ml-6 w-full">
|
||||
<div className="flex w-full">
|
||||
<MenuDesktop handleHeaderTitleChange={this.handleHeaderTitleChange}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="hidden sm:hidden" id="mobile-menu">
|
||||
<div className="px-2 pt2 pb-3 space-y-1">
|
||||
<MenuMobile handleHeaderTitleChange={this.handleHeaderTitleChange}/>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default Navbar;
|
22
src/components/RouteMenu.tsx
Normal file
22
src/components/RouteMenu.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import {Routes, Route, RouteProps} from "react-router-dom";
|
||||
import React from "react";
|
||||
import Artifacts from "./pages/Artifacts";
|
||||
|
||||
interface RouteMenuProps extends RouteProps{
|
||||
handleHeaderTitleChange: (title: string) => void;
|
||||
}
|
||||
export default function RouteMenu(props: RouteMenuProps) {
|
||||
const defaultProps = {
|
||||
handleHeaderTitleChange: props.handleHeaderTitleChange
|
||||
};
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/" element={
|
||||
<div>Nothing Here</div>
|
||||
}/>
|
||||
<Route path="/artifact" element={
|
||||
<Artifacts/>
|
||||
}/>
|
||||
</Routes>
|
||||
);
|
||||
}
|
189
src/components/pages/Artifacts.tsx
Normal file
189
src/components/pages/Artifacts.tsx
Normal file
@ -0,0 +1,189 @@
|
||||
import {ChangeEvent, useEffect, useState} from "react";
|
||||
import ReliquaryDataProvider, {IReliquaryAffix, IReliquaryMain} from "../providers/ReliquaryDataProvider";
|
||||
import {Autocomplete, Chip, createFilterOptions, TextField} from "@mui/material";
|
||||
//@ts-ignore
|
||||
import _ from "lodash";
|
||||
|
||||
interface IArtifact {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function Artifacts() {
|
||||
const [reliquaryMains, setReliquaryMains] = useState<IReliquaryMain[]>([]);
|
||||
const [reliquaryAffixes, setReliquaryAffixes] = useState<IReliquaryAffix[]>([]);
|
||||
const [uid, setUid] = useState(0);
|
||||
const [selectedArtifact, setSelectedArtifact] = useState(0);
|
||||
const [selectedMainStat, setSelectedMainStat] = useState(0);
|
||||
const [selectedAffixes, setSelectedAffixes] = useState<number[]>([]);
|
||||
const [selectedAffixesAmount, setSelectedAffixesAmount] = useState<Record<number, number>>({});
|
||||
|
||||
|
||||
const [artifactData, setArtifactData] = useState<IArtifact[]>([]);
|
||||
const [generatedArtifact, setGeneratedArtifact] = useState("/giveart ");
|
||||
|
||||
useEffect(() => {
|
||||
const dataArtifact: IArtifact[] = [];
|
||||
const initReliquaryData = async () => {
|
||||
await ReliquaryDataProvider.init();
|
||||
setReliquaryMains(ReliquaryDataProvider.getReliquaryMains());
|
||||
setReliquaryAffixes(ReliquaryDataProvider.getReliquaryAffixes());
|
||||
};
|
||||
fetch("https://gist.githubusercontent.com/exzork/0c5ab10f35f6aa718735380d8ce585db/raw/bc14a3f87f3a49aa053a43db999d04a8f09dcd71/GM%2520Handbook.txt")
|
||||
.then(res => res.text())
|
||||
.then(text => {
|
||||
const lines = text.split("\n");
|
||||
lines.forEach(line => {
|
||||
const lineSplit = line.split(" : ");
|
||||
if (lineSplit.length === 2) {
|
||||
const id = parseInt(lineSplit[0]);
|
||||
const name = lineSplit[1];
|
||||
if ((id >= 23341 && id <= 30000) || (id >= 51110 && id <= 99554)) {
|
||||
if (dataArtifact.filter((x) => x.name === lineSplit[1]).length === 0) {
|
||||
dataArtifact.push({id: id, name: name});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
setArtifactData(dataArtifact);
|
||||
initReliquaryData();
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
handleGeneratedArtifact()
|
||||
}, [uid, selectedArtifact, selectedMainStat, selectedAffixes, selectedAffixesAmount]);
|
||||
|
||||
const handleArtifactChange = (event: any, value: any) => {
|
||||
if (value !== null) {
|
||||
setSelectedArtifact(value.id);
|
||||
}
|
||||
};
|
||||
|
||||
const handleMainStatChange = (event: any, value: any) => {
|
||||
if (value !== null) {
|
||||
setSelectedMainStat(value.Id);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAffixSelected = (event: ChangeEvent<HTMLInputElement>, amount = false, affixId=0) => {
|
||||
let newSelectedAffixes = [...selectedAffixes];
|
||||
let newSelectedAffixesAmount = {...selectedAffixesAmount};
|
||||
if (amount) {
|
||||
newSelectedAffixesAmount[affixId]=Number(event.target.value);
|
||||
} else {
|
||||
if (newSelectedAffixes.indexOf(Number(event.currentTarget.value)) === -1) {
|
||||
newSelectedAffixes.push(Number(event.currentTarget.value));
|
||||
newSelectedAffixesAmount[Number(event.currentTarget.value)] = 1;
|
||||
} else {
|
||||
newSelectedAffixes.splice(newSelectedAffixes.indexOf(Number(event.currentTarget.value)), 1);
|
||||
newSelectedAffixesAmount[Number(event.currentTarget.value)] = 0;
|
||||
}
|
||||
}
|
||||
setSelectedAffixes(newSelectedAffixes);
|
||||
setSelectedAffixesAmount(newSelectedAffixesAmount);
|
||||
};
|
||||
|
||||
const getPercent = (affix:IReliquaryAffix)=>{
|
||||
if (affix.PropType.indexOf("PERCENT") !== -1 || affix.PropType.indexOf("CRITICAL") !== -1 || affix.PropType.indexOf("EFFICIENCY") !== -1 || affix.PropType.indexOf("HURT") !== -1) {
|
||||
return parseFloat(String(affix.PropValue*100)).toPrecision(3) + "%";
|
||||
}
|
||||
return parseInt(String(affix.PropValue));
|
||||
};
|
||||
|
||||
const handleGeneratedArtifact = () => {
|
||||
let selectedAffixesCombine: (string | number)[] = [];
|
||||
if (selectedAffixes.length > 0) {
|
||||
selectedAffixesCombine = selectedAffixes.map(x => {
|
||||
if (selectedAffixesAmount[x] > 1) {
|
||||
return x + "," + selectedAffixesAmount[x];
|
||||
}
|
||||
return x;
|
||||
});
|
||||
}
|
||||
const generated = "/giveart "+uid+" "+selectedArtifact+" "+selectedMainStat+" "+selectedAffixesCombine.join(" ")+" 21";
|
||||
setGeneratedArtifact(generated);
|
||||
};
|
||||
|
||||
return (
|
||||
<form method="POST" className="space-y-8 divide-y divide-gray-200 bg-white p-10">
|
||||
<div className="space-y-8 divide-y divide-gray-200 sm:space-y-5">
|
||||
<div>
|
||||
<div>
|
||||
<p className="mt-1 max-w-2xl text-sm text-gray-500">Please fill artifact details</p>
|
||||
</div>
|
||||
<div className="mt-6 sm:mt-5 space-y-6 sm:space-y-5">
|
||||
<div
|
||||
className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
|
||||
<label htmlFor="name"
|
||||
className="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
|
||||
UID
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<input type="text" aria-label="UID" name="uid" id="uid" className="block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300 rounded-md" onChange={(event) => setUid(parseInt(event.target.value))}/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
|
||||
<label htmlFor="description"
|
||||
className="block text-sm font-medium leading-5 text-gray-700 sm:mt-px sm:pt-2">
|
||||
Artifact Name
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<Autocomplete
|
||||
aria-label="Artifact Name" id="ArtifactName"
|
||||
className="block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300 rounded-md"
|
||||
options={artifactData}
|
||||
getOptionLabel={(option) => option.name}
|
||||
onChange={handleArtifactChange}
|
||||
renderInput={(params) => <TextField {...params} label="Artifact Name" variant="outlined"/>}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
|
||||
<label htmlFor="image"
|
||||
className="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
|
||||
Main Stats
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2">
|
||||
<div
|
||||
className="relative h-10 rounded-lg flex justify-center items-center">
|
||||
<Autocomplete
|
||||
aria-label="Artifact Main Stats" id="ArtifactMainStats"
|
||||
className="block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300 rounded-md"
|
||||
options={reliquaryMains}
|
||||
getOptionLabel={(option) => option.PropType}
|
||||
onChange={handleMainStatChange}
|
||||
renderInput={(params) => <TextField {...params} label="Main Stats" variant="outlined"/>}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
|
||||
<label htmlFor="start_date"
|
||||
className="block text-sm font-medium leading-5 text-gray-700 sm:mt-px sm:pt-2">
|
||||
Artifact Sub Stats
|
||||
</label>
|
||||
<div className="mt-1 sm:mt-0 sm:col-span-2 h-48 overflow-auto">
|
||||
{reliquaryAffixes.map((affix, index) => {
|
||||
return (
|
||||
<div key={index} className="flex">
|
||||
<input type="checkbox" className="mr-4 ml-4 focus:ring-indigo-500 h-4 w-4 mt-1 text-indigo-600 border-gray-300 rounded" value={affix.Id} id={"select-"+affix.Id} onChange={(e)=>handleAffixSelected(e,false,0)}/>
|
||||
<label className="flex-grow" htmlFor={"select-"+affix.Id}>{affix.PropType +" - "+getPercent(affix)}</label>
|
||||
<input type="number" defaultValue="1" min="1" className="flex-none block shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300 rounded-md" onChange={(e)=>handleAffixSelected(e,true, affix.Id)}/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="block sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
|
||||
<input type="text" onClick={(e)=>{navigator.clipboard.writeText(e.currentTarget.value)}} className="block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300 rounded-md" value={generatedArtifact} readOnly/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
46
src/components/providers/ReliquaryDataProvider.ts
Normal file
46
src/components/providers/ReliquaryDataProvider.ts
Normal file
@ -0,0 +1,46 @@
|
||||
export interface IReliquaryMain {
|
||||
Id: number;
|
||||
PropDepotId: number;
|
||||
PropType:string;
|
||||
AffixName:string;
|
||||
}
|
||||
export interface IReliquaryAffix {
|
||||
Id: number;
|
||||
DepotId: number;
|
||||
GroupId: number;
|
||||
PropType:string;
|
||||
PropValue:number;
|
||||
}
|
||||
export default class ReliquaryDataProvider {
|
||||
private static reliquaryMains:IReliquaryMain[] = [];
|
||||
private static reliquaryAffixes:IReliquaryAffix[] = [];
|
||||
|
||||
public static async init(){
|
||||
await this.loadReliquaryMain();
|
||||
await this.loadReliquaryAffixes();
|
||||
}
|
||||
|
||||
private static async loadReliquaryMain(){
|
||||
let data = await fetch("https://raw.githubusercontent.com/Dimbreath/GenshinData/master/ExcelBinOutput/ReliquaryMainPropExcelConfigData.json");
|
||||
let json:IReliquaryMain[] = await data.json();
|
||||
this.reliquaryMains = [];
|
||||
json.forEach(element => {
|
||||
if (this.reliquaryMains.filter(x => x.PropType === element.PropType).length === 0)
|
||||
this.reliquaryMains.push(element)
|
||||
});
|
||||
}
|
||||
|
||||
private static async loadReliquaryAffixes(){
|
||||
let data = await fetch("https://raw.githubusercontent.com/Dimbreath/GenshinData/master/ExcelBinOutput/ReliquaryAffixExcelConfigData.json");
|
||||
let json = await data.json();
|
||||
this.reliquaryAffixes = json;
|
||||
}
|
||||
|
||||
public static getReliquaryMains():IReliquaryMain[]{
|
||||
return this.reliquaryMains;
|
||||
}
|
||||
|
||||
public static getReliquaryAffixes():IReliquaryAffix[]{
|
||||
return this.reliquaryAffixes;
|
||||
}
|
||||
}
|
@ -11,3 +11,6 @@ code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
11
tailwind.config.js
Normal file
11
tailwind.config.js
Normal file
@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
content: [
|
||||
"./src/**/*.{js,jsx,ts,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [
|
||||
require('@tailwindcss/forms')
|
||||
],
|
||||
}
|
Loading…
Reference in New Issue
Block a user