]> git.localhorst.tv Git - alttp.git/blob - resources/js/pages/DoorsTracker.js
compact keysanity tracker
[alttp.git] / resources / js / pages / DoorsTracker.js
1 import React from 'react';
2 import { Helmet } from 'react-helmet';
3
4 import ZeldaIcon from '../components/common/ZeldaIcon';
5
6 const DUNGEONS = [
7         'hc',
8         'ct',
9         'ep',
10         'dp',
11         'th',
12         'pd',
13         'sp',
14         'sw',
15         'tt',
16         'ip',
17         'mm',
18         'tr',
19         'gt',
20 ];
21
22 const ITEMS = [
23         'compass',
24         'map',
25         'big-key',
26         'bow',
27         'hookshot',
28         'fire-rod',
29         'lamp',
30         'hammer',
31         'somaria',
32         'fighter-sword',
33         'boots',
34         'glove',
35         'flippers',
36 ];
37
38 const ITEM_CLASSES = {
39         'compass': 'dungeon-item',
40         'map': 'dungeon-item',
41         'big-key': 'dungeon-item',
42         'bow': 'item',
43         'hookshot': 'item',
44         'fire-rod': 'item',
45         'lamp': 'item',
46         'hammer': 'item',
47         'somaria': 'item',
48         'fighter-sword': 'item',
49         'boots': 'item',
50         'glove': 'item',
51         'flippers': 'item',
52 };
53
54 const nextCSwitch = cur => {
55         switch (cur) {
56                 case 'blue':
57                         return 'red';
58                 case 'red':
59                         return '';
60                 default:
61                         return 'blue';
62         }
63 };
64
65 const prevCSwitch = cur => nextCSwitch(nextCSwitch(cur));
66
67 export const Component = () => {
68         const [state, setState] = React.useState(DUNGEONS.reduce((state, dungeon) => ({
69                 ...state,
70                 [dungeon]: ITEMS.reduce((items, item) => ({
71                         ...items,
72                         [item]: false,
73                 }), {
74                         boss: true,
75                         cswitch: '',
76                         keys: 1,
77                 }),
78         }), {}));
79
80         const handleItemClick = React.useCallback((dungeon, item) => e => {
81                 setState(state => ({
82                         ...state,
83                         [dungeon]: {
84                                 ...state[dungeon],
85                                 [item]: !state[dungeon][item],
86                         },
87                 }));
88                 e.preventDefault();
89                 e.stopPropagation();
90         });
91
92         const handleCSwitchClick = React.useCallback(dungeon => e => {
93                 setState(state => ({
94                         ...state,
95                         [dungeon]: {
96                                 ...state[dungeon],
97                                 cswitch: nextCSwitch(state[dungeon].cswitch),
98                         },
99                 }));
100                 e.preventDefault();
101                 e.stopPropagation();
102         });
103
104         const handleCSwitchRightClick = React.useCallback(dungeon => e => {
105                 setState(state => ({
106                         ...state,
107                         [dungeon]: {
108                                 ...state[dungeon],
109                                 cswitch: prevCSwitch(state[dungeon].cswitch),
110                         },
111                 }));
112                 e.preventDefault();
113                 e.stopPropagation();
114         });
115
116         const handleKeysClick = React.useCallback(dungeon => e => {
117                 setState(state => ({
118                         ...state,
119                         [dungeon]: {
120                                 ...state[dungeon],
121                                 keys: state[dungeon].keys + 1,
122                         },
123                 }));
124                 e.preventDefault();
125                 e.stopPropagation();
126         });
127
128         const handleKeysRightClick = React.useCallback(dungeon => e => {
129                 setState(state => ({
130                         ...state,
131                         [dungeon]: {
132                                 ...state[dungeon],
133                                 keys: Math.max(state[dungeon].keys - 1, 0),
134                         },
135                 }));
136                 e.preventDefault();
137                 e.stopPropagation();
138         });
139
140         return <>
141                 <Helmet>
142                         <title>Doors Tracker</title>
143                         <meta name="description" content="Doors Tracker" />
144                 </Helmet>
145                 <div className="doors-tracker d-flex flex-column">
146                         {DUNGEONS.map(dungeon =>
147                                 <div className="d-flex flex-row" key={dungeon}>
148                                         <div
149                                                 className={`cell ${state[dungeon].boss ? 'on' : 'off'} dungeon`}
150                                                 onClick={handleItemClick(dungeon, 'boss')}
151                                         >
152                                                 <ZeldaIcon name={`dungeon-${dungeon}`} />
153                                         </div>
154                                         <div
155                                                 className={`cell ${state[dungeon].keys ? 'on' : 'off'} keys`}
156                                                 onClick={handleKeysClick(dungeon)}
157                                                 onContextMenu={handleKeysRightClick(dungeon)}
158                                         >
159                                                 {state[dungeon].keys}
160                                         </div>
161                                         <div
162                                                 className={`cell ${state[dungeon].cswitch ? 'on' : 'off'} cswitch`}
163                                                 onClick={handleCSwitchClick(dungeon)}
164                                                 onContextMenu={handleCSwitchRightClick(dungeon)}
165                                         >
166                                                 <ZeldaIcon name={state[dungeon].cswitch
167                                                         ? `crystal-switch-${state[dungeon].cswitch}`
168                                                         : 'crystal-switch'
169                                                 } />
170                                         </div>
171                                         {ITEMS.map(item =>
172                                                 <div
173                                                         className={
174                                                                 `cell ${state[dungeon][item] ? 'on' : 'off'} ${ITEM_CLASSES[item]}`
175                                                         }
176                                                         key={item}
177                                                         onClick={handleItemClick(dungeon, item)}
178                                                 >
179                                                         <ZeldaIcon name={item} />
180                                                 </div>
181                                         )}
182                                 </div>
183                         )}
184                 </div>
185         </>;
186 };