ability to cancel construction and have a portion of the funds returned
[browser-rts.git] / src / render / land-development.ts
1 import { BuildQueue } from "../repository/build-queue";
2 import { CityWithLocation } from "../repository/city";
3 import { Building } from '../repository/buildings';
4 import _ from "lodash";
5
6 const emptyBuilding: BuildQueue = {
7   id: '',
8   owner: '',
9   amount: 0,
10   created: 0,
11   due: 0,
12   building_type: 'empty',
13 };
14
15 function progressBar(current: number, max: number): string {
16     const percent = Math.ceil((current/max) * 100);
17     return `
18     <div class="progress-bar construction" style="background: background: var(--green-bg);
19     background: linear-gradient(90deg, var(--green-bg) 0%, var(--green-bg) ${percent}%, #000 ${percent}%); border-color: var(--green-border); ">
20     ${percent}%
21     </div>
22     `;
23 }
24
25 export function renderLandDevelopment(city: CityWithLocation, buildings: Building[], buildQueues: BuildQueue[]): string {
26     const freeSpace = city.totalSpace - city.usedSpace;
27     const sortedBuildQueues = buildQueues.sort((a, b) => {
28         return a.due - b.due;
29     });
30
31     let html = `
32     <div hx-trigger="reload-construction-queue, every 600s" hx-get="/poll/construction">
33     <h2 data-augmented-ui="tl-clip bl-clip none">Construction</h2>
34     <table>
35     <tr>
36         <th>Type</th>
37         <th>Current</th>
38         <th>Space Available: ${(city.totalSpace - city.usedSpace).toLocaleString()} (${Math.ceil(freeSpace/city.totalSpace * 100)}% available)</th>
39         <th width="200">Cost</th>
40     </tr>
41     ${
42         buildings.map(building => {
43             return `
44             <tr>
45                 <th>${building.display}</th>
46                 <td>${city[building.slug]}</td>
47                 <td>
48                     <form hx-post="/build" hx-swap="innerHTML" hx-target="#notifications">
49                         <input type="number" size="6" name="amount" hx-post="/cost/construction" hx-trigger="keyup" hx-target="#${building.slug}-cost" hx-swap="innerHTML">
50                         <input type="hidden" name="building_type" value="${building.slug}">
51                         <button type="submit">Build</button>
52                     </form>
53                 </td>
54                 <td id="${building.slug}-cost"></td>
55             </tr>
56             `;
57         }).join("\n")
58     }
59     </table>
60     `;
61
62     const quickFindBuilding = _.keyBy(buildings, 'slug');
63     const finalBuildQueues = sortedBuildQueues;
64
65     if (finalBuildQueues.length < city.max_construction_queue) {
66       while(finalBuildQueues.length < city.max_construction_queue) {
67         finalBuildQueues.push(emptyBuilding);
68       }
69     }
70
71
72     const queues = `
73     <hr>
74     <h2 data-augmented-ui="tl-clip bl-clip none">Build Queues</h2>
75     <table>
76     <tr>
77     <th align="left">Building</th>
78     <th align="left">Amount Expected</th>
79     <th colspan="2">Progress</th>
80     </tr>
81     ${sortedBuildQueues.map(queue => {
82       if(queue.building_type === 'empty') {
83         return `
84         <tr>
85         <td colspan="4">You have sufficient capacity to build something.</td>
86         </tr>
87         `
88       }
89       else {
90         const now = Date.now() - queue.created;
91         const duration = queue.due - queue.created;
92
93         return `
94         <tr>
95         <td>${quickFindBuilding[queue.building_type].display}</td>
96         <td>${queue.amount}</td>
97         <td>${progressBar(now, duration)}</td>
98         <td width="50">
99         <a href="#" hx-post="/construction/${queue.id}/cancel" hx-trigger="click" class="danger-text close" title="Cancel Construction">&times;</a>
100         </td>
101         </tr>
102         `;
103       }
104     }).join("\n")}
105     </table>
106     </div>
107     `;
108     return html + queues;
109 }