diff options
Diffstat (limited to 'frontend/src/components/Summary.tsx')
| -rw-r--r-- | frontend/src/components/Summary.tsx | 265 |
1 files changed, 176 insertions, 89 deletions
diff --git a/frontend/src/components/Summary.tsx b/frontend/src/components/Summary.tsx index 4bcaa6a..1ba166a 100644 --- a/frontend/src/components/Summary.tsx +++ b/frontend/src/components/Summary.tsx | |||
| @@ -2,49 +2,67 @@ import React from 'react'; | |||
| 2 | import ReactMarkdown from 'react-markdown'; | 2 | import ReactMarkdown from 'react-markdown'; |
| 3 | 3 | ||
| 4 | import { MapSummary } from '@customTypes/Map'; | 4 | import { MapSummary } from '@customTypes/Map'; |
| 5 | import "@css/Maps.css" | 5 | import '@css/Maps.css'; |
| 6 | 6 | ||
| 7 | interface SummaryProps { | 7 | interface SummaryProps { |
| 8 | selectedRun: number | 8 | selectedRun: number; |
| 9 | setSelectedRun: (x: number) => void; | 9 | setSelectedRun: (x: number) => void; |
| 10 | data: MapSummary; | 10 | data: MapSummary; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | const Summary: React.FC<SummaryProps> = ({ selectedRun, setSelectedRun, data }) => { | 13 | const Summary: React.FC<SummaryProps> = ({ |
| 14 | 14 | selectedRun, | |
| 15 | setSelectedRun, | ||
| 16 | data, | ||
| 17 | }) => { | ||
| 15 | const [selectedCategory, setSelectedCategory] = React.useState<number>(1); | 18 | const [selectedCategory, setSelectedCategory] = React.useState<number>(1); |
| 16 | const [historySelected, setHistorySelected] = React.useState<boolean>(false); | 19 | const [historySelected, setHistorySelected] = React.useState<boolean>(false); |
| 17 | 20 | ||
| 18 | function _select_run(idx: number, category_id: number) { | 21 | function _select_run(idx: number, category_id: number) { |
| 19 | let r = document.querySelectorAll("button.record"); | 22 | let r = document.querySelectorAll('button.record'); |
| 20 | r.forEach(e => (e as HTMLElement).style.backgroundColor = "#2b2e46"); | 23 | r.forEach(e => ((e as HTMLElement).style.backgroundColor = '#2b2e46')); |
| 21 | (r[idx] as HTMLElement).style.backgroundColor = "#161723" | 24 | (r[idx] as HTMLElement).style.backgroundColor = '#161723'; |
| 22 | |||
| 23 | 25 | ||
| 24 | if (data && data.summary.routes.length !== 0) { | 26 | if (data && data.summary.routes.length !== 0) { |
| 25 | idx += data.summary.routes.filter(e => e.category.id < category_id).length // lethimcook | 27 | idx += data.summary.routes.filter( |
| 28 | e => e.category.id < category_id | ||
| 29 | ).length; // lethimcook | ||
| 26 | setSelectedRun(idx); | 30 | setSelectedRun(idx); |
| 27 | } | 31 | } |
| 28 | }; | 32 | } |
| 29 | 33 | ||
| 30 | function _get_youtube_id(url: string): string { | 34 | function _get_youtube_id(url: string): string { |
| 31 | const urlArray = url.split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/); | 35 | const urlArray = url.split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/); |
| 32 | return (urlArray[2] !== undefined) ? urlArray[2].split(/[^0-9a-z_-]/i)[0] : urlArray[0]; | 36 | return urlArray[2] !== undefined |
| 33 | }; | 37 | ? urlArray[2].split(/[^0-9a-z_-]/i)[0] |
| 38 | : urlArray[0]; | ||
| 39 | } | ||
| 34 | 40 | ||
| 35 | function _category_change() { | 41 | function _category_change() { |
| 36 | const btn = document.querySelectorAll("#section3 #category span button"); | 42 | const btn = document.querySelectorAll('#section3 #category span button'); |
| 37 | btn.forEach((e) => { (e as HTMLElement).style.backgroundColor = "#2b2e46" }); | 43 | btn.forEach(e => { |
| 44 | (e as HTMLElement).style.backgroundColor = '#2b2e46'; | ||
| 45 | }); | ||
| 38 | // heavenly father forgive me for i have sinned. TODO: fix this bullshit with dynamic categories | 46 | // heavenly father forgive me for i have sinned. TODO: fix this bullshit with dynamic categories |
| 39 | const idx = selectedCategory === 1 ? 0 : data.map.is_coop ? selectedCategory - 3 : selectedCategory - 1; | 47 | const idx = |
| 40 | (btn[idx] as HTMLElement).style.backgroundColor = "#202232"; | 48 | selectedCategory === 1 |
| 41 | }; | 49 | ? 0 |
| 50 | : data.map.is_coop | ||
| 51 | ? selectedCategory - 3 | ||
| 52 | : selectedCategory - 1; | ||
| 53 | (btn[idx] as HTMLElement).style.backgroundColor = '#202232'; | ||
| 54 | } | ||
| 42 | 55 | ||
| 43 | function _history_change() { | 56 | function _history_change() { |
| 44 | const btn = document.querySelectorAll("#section3 #history span button"); | 57 | const btn = document.querySelectorAll('#section3 #history span button'); |
| 45 | btn.forEach((e) => { (e as HTMLElement).style.backgroundColor = "#2b2e46" }); | 58 | btn.forEach(e => { |
| 46 | (historySelected ? btn[1] as HTMLElement : btn[0] as HTMLElement).style.backgroundColor = "#202232"; | 59 | (e as HTMLElement).style.backgroundColor = '#2b2e46'; |
| 47 | }; | 60 | }); |
| 61 | (historySelected | ||
| 62 | ? (btn[1] as HTMLElement) | ||
| 63 | : (btn[0] as HTMLElement) | ||
| 64 | ).style.backgroundColor = '#202232'; | ||
| 65 | } | ||
| 48 | 66 | ||
| 49 | React.useEffect(() => { | 67 | React.useEffect(() => { |
| 50 | _history_change(); | 68 | _history_change(); |
| @@ -61,119 +79,188 @@ const Summary: React.FC<SummaryProps> = ({ selectedRun, setSelectedRun, data }) | |||
| 61 | 79 | ||
| 62 | return ( | 80 | return ( |
| 63 | <> | 81 | <> |
| 64 | <section id='section3' className='summary1'> | 82 | <section id="section3" className="summary1"> |
| 65 | <div id='category' | 83 | <div |
| 66 | style={data.map.image === "" ? { backgroundColor: "#202232" } : {}}> | 84 | id="category" |
| 67 | <img src={data.map.image} alt="" id='category-image'></img> | 85 | style={data.map.image === '' ? { backgroundColor: '#202232' } : {}} |
| 68 | <p><span className='portal-count'>{data.summary.routes[selectedRun].history.score_count}</span> | 86 | > |
| 69 | {data.summary.routes[selectedRun].history.score_count === 1 ? ` portal` : ` portals`}</p> | 87 | <img src={data.map.image} alt="" id="category-image"></img> |
| 70 | {data.map.is_coop ? // TODO: make this part dynamic | 88 | <p> |
| 71 | ( | 89 | <span className="portal-count"> |
| 72 | <span style={{ gridTemplateColumns: "1fr 1fr 1fr" }}> | 90 | {data.summary.routes[selectedRun].history.score_count} |
| 73 | <button onClick={() => setSelectedCategory(1)}>CM</button> | 91 | </span> |
| 74 | <button onClick={() => setSelectedCategory(4)}>Any%</button> | 92 | {data.summary.routes[selectedRun].history.score_count === 1 |
| 75 | <button onClick={() => setSelectedCategory(5)}>All Courses</button> | 93 | ? ` portal` |
| 76 | </span> | 94 | : ` portals`} |
| 77 | ) | 95 | </p> |
| 78 | : | 96 | {data.map.is_coop ? ( // TODO: make this part dynamic |
| 79 | ( | 97 | <span style={{ gridTemplateColumns: '1fr 1fr 1fr' }}> |
| 80 | <span style={{ gridTemplateColumns: "1fr 1fr 1fr 1fr" }}> | 98 | <button onClick={() => setSelectedCategory(1)}>CM</button> |
| 81 | 99 | <button onClick={() => setSelectedCategory(4)}>Any%</button> | |
| 82 | <button onClick={() => setSelectedCategory(1)}>CM</button> | 100 | <button onClick={() => setSelectedCategory(5)}> |
| 83 | <button onClick={() => setSelectedCategory(2)}>NoSLA</button> | 101 | All Courses |
| 84 | <button onClick={() => setSelectedCategory(3)}>Inbounds SLA</button> | 102 | </button> |
| 85 | <button onClick={() => setSelectedCategory(4)}>Any%</button> | 103 | </span> |
| 86 | </span> | 104 | ) : ( |
| 87 | ) | 105 | <span style={{ gridTemplateColumns: '1fr 1fr 1fr 1fr' }}> |
| 88 | } | 106 | <button onClick={() => setSelectedCategory(1)}>CM</button> |
| 89 | 107 | <button onClick={() => setSelectedCategory(2)}>NoSLA</button> | |
| 108 | <button onClick={() => setSelectedCategory(3)}> | ||
| 109 | Inbounds SLA | ||
| 110 | </button> | ||
| 111 | <button onClick={() => setSelectedCategory(4)}>Any%</button> | ||
| 112 | </span> | ||
| 113 | )} | ||
| 90 | </div> | 114 | </div> |
| 91 | 115 | ||
| 92 | <div id='history'> | 116 | <div id="history"> |
| 93 | 117 | <div style={{ display: historySelected ? 'none' : 'block' }}> | |
| 94 | <div style={{ display: historySelected ? "none" : "block" }}> | 118 | {data.summary.routes.filter(e => e.category.id === selectedCategory) |
| 95 | {data.summary.routes.filter(e => e.category.id === selectedCategory).length === 0 ? <h5>There are no records for this map.</h5> : | 119 | .length === 0 ? ( |
| 120 | <h5>There are no records for this map.</h5> | ||
| 121 | ) : ( | ||
| 96 | <> | 122 | <> |
| 97 | <div className='record-top'> | 123 | <div className="record-top"> |
| 98 | <span>Date</span> | 124 | <span>Date</span> |
| 99 | <span>Record</span> | 125 | <span>Record</span> |
| 100 | <span>First Completion</span> | 126 | <span>First Completion</span> |
| 101 | </div> | 127 | </div> |
| 102 | <hr /> | 128 | <hr /> |
| 103 | <div id='records'> | 129 | <div id="records"> |
| 104 | |||
| 105 | {data.summary.routes | 130 | {data.summary.routes |
| 106 | .filter(e => e.category.id === selectedCategory) | 131 | .filter(e => e.category.id === selectedCategory) |
| 107 | .map((r, index) => ( | 132 | .map((r, index) => ( |
| 108 | <button className='record' key={index} onClick={() => { | 133 | <button |
| 109 | _select_run(index, r.category.id); | 134 | className="record" |
| 110 | }}> | 135 | key={index} |
| 111 | <span>{new Date(r.history.date).toLocaleDateString( | 136 | onClick={() => { |
| 112 | "en-US", { month: 'long', day: 'numeric', year: 'numeric' } | 137 | _select_run(index, r.category.id); |
| 113 | )}</span> | 138 | }} |
| 139 | > | ||
| 140 | <span> | ||
| 141 | {new Date(r.history.date).toLocaleDateString( | ||
| 142 | 'en-US', | ||
| 143 | { month: 'long', day: 'numeric', year: 'numeric' } | ||
| 144 | )} | ||
| 145 | </span> | ||
| 114 | <span>{r.history.score_count}</span> | 146 | <span>{r.history.score_count}</span> |
| 115 | <span>{r.history.runner_name}</span> | 147 | <span>{r.history.runner_name}</span> |
| 116 | </button> | 148 | </button> |
| 117 | ))} | 149 | ))} |
| 118 | </div> | 150 | </div> |
| 119 | </> | 151 | </> |
| 120 | } | 152 | )} |
| 121 | </div> | 153 | </div> |
| 122 | 154 | ||
| 123 | <div style={{ display: historySelected ? "block" : "none" }}> | 155 | <div style={{ display: historySelected ? 'block' : 'none' }}> |
| 124 | {data.summary.routes.filter(e => e.category.id === selectedCategory).length === 0 ? <h5>There are no records for this map.</h5> : | 156 | {data.summary.routes.filter(e => e.category.id === selectedCategory) |
| 125 | <div id='graph'> | 157 | .length === 0 ? ( |
| 158 | <h5>There are no records for this map.</h5> | ||
| 159 | ) : ( | ||
| 160 | <div id="graph"> | ||
| 126 | {/* <div>{graph(1)}</div> | 161 | {/* <div>{graph(1)}</div> |
| 127 | <div>{graph(2)}</div> | 162 | <div>{graph(2)}</div> |
| 128 | <div>{graph(3)}</div> */} | 163 | <div>{graph(3)}</div> */} |
| 129 | </div> | 164 | </div> |
| 130 | } | 165 | )} |
| 131 | </div> | 166 | </div> |
| 132 | <span> | 167 | <span> |
| 133 | <button onClick={() => setHistorySelected(false)}>List</button> | 168 | <button onClick={() => setHistorySelected(false)}>List</button> |
| 134 | <button onClick={() => setHistorySelected(true)}>Graph</button> | 169 | <button onClick={() => setHistorySelected(true)}>Graph</button> |
| 135 | </span> | 170 | </span> |
| 136 | </div> | 171 | </div> |
| 137 | 172 | </section> | |
| 138 | 173 | <section id="section4" className="summary1"> | |
| 139 | </section > | 174 | <div id="difficulty"> |
| 140 | <section id='section4' className='summary1'> | ||
| 141 | <div id='difficulty'> | ||
| 142 | <span>Difficulty</span> | 175 | <span>Difficulty</span> |
| 143 | {data.summary.routes[selectedRun].rating === 0 && (<span>N/A</span>)} | 176 | {data.summary.routes[selectedRun].rating === 0 && <span>N/A</span>} |
| 144 | {data.summary.routes[selectedRun].rating === 1 && (<span style={{ color: "lime" }}>Very easy</span>)} | 177 | {data.summary.routes[selectedRun].rating === 1 && ( |
| 145 | {data.summary.routes[selectedRun].rating === 2 && (<span style={{ color: "green" }}>Easy</span>)} | 178 | <span style={{ color: 'lime' }}>Very easy</span> |
| 146 | {data.summary.routes[selectedRun].rating === 3 && (<span style={{ color: "yellow" }}>Medium</span>)} | 179 | )} |
| 147 | {data.summary.routes[selectedRun].rating === 4 && (<span style={{ color: "orange" }}>Hard</span>)} | 180 | {data.summary.routes[selectedRun].rating === 2 && ( |
| 148 | {data.summary.routes[selectedRun].rating === 5 && (<span style={{ color: "red" }}>Very hard</span>)} | 181 | <span style={{ color: 'green' }}>Easy</span> |
| 182 | )} | ||
| 183 | {data.summary.routes[selectedRun].rating === 3 && ( | ||
| 184 | <span style={{ color: 'yellow' }}>Medium</span> | ||
| 185 | )} | ||
| 186 | {data.summary.routes[selectedRun].rating === 4 && ( | ||
| 187 | <span style={{ color: 'orange' }}>Hard</span> | ||
| 188 | )} | ||
| 189 | {data.summary.routes[selectedRun].rating === 5 && ( | ||
| 190 | <span style={{ color: 'red' }}>Very hard</span> | ||
| 191 | )} | ||
| 149 | <div> | 192 | <div> |
| 150 | {data.summary.routes[selectedRun].rating === 1 ? (<div className='difficulty-rating' style={{ backgroundColor: "lime" }}></div>) : (<div className='difficulty-rating'></div>)} | 193 | {data.summary.routes[selectedRun].rating === 1 ? ( |
| 151 | {data.summary.routes[selectedRun].rating === 2 ? (<div className='difficulty-rating' style={{ backgroundColor: "green" }}></div>) : (<div className='difficulty-rating'></div>)} | 194 | <div |
| 152 | {data.summary.routes[selectedRun].rating === 3 ? (<div className='difficulty-rating' style={{ backgroundColor: "yellow" }}></div>) : (<div className='difficulty-rating'></div>)} | 195 | className="difficulty-rating" |
| 153 | {data.summary.routes[selectedRun].rating === 4 ? (<div className='difficulty-rating' style={{ backgroundColor: "orange" }}></div>) : (<div className='difficulty-rating'></div>)} | 196 | style={{ backgroundColor: 'lime' }} |
| 154 | {data.summary.routes[selectedRun].rating === 5 ? (<div className='difficulty-rating' style={{ backgroundColor: "red" }}></div>) : (<div className='difficulty-rating'></div>)} | 197 | ></div> |
| 198 | ) : ( | ||
| 199 | <div className="difficulty-rating"></div> | ||
| 200 | )} | ||
| 201 | {data.summary.routes[selectedRun].rating === 2 ? ( | ||
| 202 | <div | ||
| 203 | className="difficulty-rating" | ||
| 204 | style={{ backgroundColor: 'green' }} | ||
| 205 | ></div> | ||
| 206 | ) : ( | ||
| 207 | <div className="difficulty-rating"></div> | ||
| 208 | )} | ||
| 209 | {data.summary.routes[selectedRun].rating === 3 ? ( | ||
| 210 | <div | ||
| 211 | className="difficulty-rating" | ||
| 212 | style={{ backgroundColor: 'yellow' }} | ||
| 213 | ></div> | ||
| 214 | ) : ( | ||
| 215 | <div className="difficulty-rating"></div> | ||
| 216 | )} | ||
| 217 | {data.summary.routes[selectedRun].rating === 4 ? ( | ||
| 218 | <div | ||
| 219 | className="difficulty-rating" | ||
| 220 | style={{ backgroundColor: 'orange' }} | ||
| 221 | ></div> | ||
| 222 | ) : ( | ||
| 223 | <div className="difficulty-rating"></div> | ||
| 224 | )} | ||
| 225 | {data.summary.routes[selectedRun].rating === 5 ? ( | ||
| 226 | <div | ||
| 227 | className="difficulty-rating" | ||
| 228 | style={{ backgroundColor: 'red' }} | ||
| 229 | ></div> | ||
| 230 | ) : ( | ||
| 231 | <div className="difficulty-rating"></div> | ||
| 232 | )} | ||
| 155 | </div> | 233 | </div> |
| 156 | </div> | 234 | </div> |
| 157 | <div id='count'> | 235 | <div id="count"> |
| 158 | <span>Completion Count</span> | 236 | <span>Completion Count</span> |
| 159 | <div>{data.summary.routes[selectedRun].completion_count}</div> | 237 | <div>{data.summary.routes[selectedRun].completion_count}</div> |
| 160 | </div> | 238 | </div> |
| 161 | </section> | 239 | </section> |
| 162 | 240 | ||
| 163 | <section id='section5' className='summary1'> | 241 | <section id="section5" className="summary1"> |
| 164 | <div id='description'> | 242 | <div id="description"> |
| 165 | {data.summary.routes[selectedRun].showcase !== "" ? | 243 | {data.summary.routes[selectedRun].showcase !== '' ? ( |
| 166 | <iframe title='Showcase video' src={"https://www.youtube.com/embed/" + _get_youtube_id(data.summary.routes[selectedRun].showcase)}> </iframe> | 244 | <iframe |
| 167 | : ""} | 245 | title="Showcase video" |
| 246 | src={ | ||
| 247 | 'https://www.youtube.com/embed/' + | ||
| 248 | _get_youtube_id(data.summary.routes[selectedRun].showcase) | ||
| 249 | } | ||
| 250 | > | ||
| 251 | {' '} | ||
| 252 | </iframe> | ||
| 253 | ) : ( | ||
| 254 | '' | ||
| 255 | )} | ||
| 168 | <h3>Route Description</h3> | 256 | <h3>Route Description</h3> |
| 169 | <span id='description-text'> | 257 | <span id="description-text"> |
| 170 | <ReactMarkdown> | 258 | <ReactMarkdown> |
| 171 | {data.summary.routes[selectedRun].description} | 259 | {data.summary.routes[selectedRun].description} |
| 172 | </ReactMarkdown> | 260 | </ReactMarkdown> |
| 173 | </span> | 261 | </span> |
| 174 | </div> | 262 | </div> |
| 175 | </section> | 263 | </section> |
| 176 | |||
| 177 | </> | 264 | </> |
| 178 | ); | 265 | ); |
| 179 | }; | 266 | }; |