zerocarbon-quickstart 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codesandbox/tasks.json +19 -0
- package/.replitrc +21 -0
- package/COMPLETE_SUMMARY.md +419 -0
- package/DEPLOYMENT_GUIDE.md +437 -0
- package/README.md +228 -0
- package/README_QUICKACTION.md +364 -0
- package/SECURITY_IMPLEMENTATION.md +300 -0
- package/SETUP_GUIDE.md +643 -0
- package/YC_APPLICATION_GUIDE.md +219 -0
- package/curl-examples.sh +82 -0
- package/index.js +221 -0
- package/package.json +31 -0
- package/quickstart.py +167 -0
- package/web-demo.html +338 -0
package/quickstart.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
ZeroCarbon API - Interactive Quickstart
|
|
4
|
+
Run: python quickstart.py
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
import json
|
|
9
|
+
from typing import Dict, Any
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
# Auto-detect environment
|
|
13
|
+
API_BASE = os.environ.get('API_BASE', 'https://zerocarbon.codes/api')
|
|
14
|
+
|
|
15
|
+
# Colors for terminal output
|
|
16
|
+
class Colors:
|
|
17
|
+
RESET = '\033[0m'
|
|
18
|
+
GREEN = '\033[32m'
|
|
19
|
+
BLUE = '\033[34m'
|
|
20
|
+
YELLOW = '\033[33m'
|
|
21
|
+
CYAN = '\033[36m'
|
|
22
|
+
BOLD = '\033[1m'
|
|
23
|
+
|
|
24
|
+
def log(message: str, color: str = 'RESET'):
|
|
25
|
+
"""Print colored message to console"""
|
|
26
|
+
color_code = getattr(Colors, color, Colors.RESET)
|
|
27
|
+
print(f"{color_code}{message}{Colors.RESET}")
|
|
28
|
+
|
|
29
|
+
def api_request(endpoint: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
30
|
+
"""Make API request to ZeroCarbon"""
|
|
31
|
+
try:
|
|
32
|
+
response = requests.post(
|
|
33
|
+
f"{API_BASE}{endpoint}",
|
|
34
|
+
json=data,
|
|
35
|
+
headers={'Content-Type': 'application/json'},
|
|
36
|
+
timeout=10
|
|
37
|
+
)
|
|
38
|
+
return response.json()
|
|
39
|
+
except Exception as e:
|
|
40
|
+
return {"success": False, "error": str(e)}
|
|
41
|
+
|
|
42
|
+
def demo_electricity():
|
|
43
|
+
"""Demo: Calculate electricity emissions"""
|
|
44
|
+
log('\nš Demo 1: Electricity Emissions', 'CYAN')
|
|
45
|
+
log('Calculating emissions for 1,000 kWh of electricity in the US...\n')
|
|
46
|
+
|
|
47
|
+
result = api_request('/v1/emissions/calculate', {
|
|
48
|
+
'source': 'electricity',
|
|
49
|
+
'value': 1000,
|
|
50
|
+
'unit': 'kWh',
|
|
51
|
+
'country': 'US'
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
if result.get('success'):
|
|
55
|
+
data = result.get('data', {})
|
|
56
|
+
log(f"ā
Emissions: {data.get('emissions_kg_co2e')} kg CO2e", 'GREEN')
|
|
57
|
+
log(f" Equivalent to: {data.get('emissions_kg_co2e', 0) / 411:.1f} gallons of gasoline", 'BLUE')
|
|
58
|
+
log(f" Emission factor: {data.get('emission_factor')} kg CO2e per kWh", 'BLUE')
|
|
59
|
+
|
|
60
|
+
def demo_flight():
|
|
61
|
+
"""Demo: Calculate flight emissions"""
|
|
62
|
+
log('\nāļø Demo 2: Flight Emissions', 'CYAN')
|
|
63
|
+
log('Calculating emissions for SFO ā JFK flight...\n')
|
|
64
|
+
|
|
65
|
+
result = api_request('/v1/calculate/flight', {
|
|
66
|
+
'from': 'SFO',
|
|
67
|
+
'to': 'JFK',
|
|
68
|
+
'passengers': 1,
|
|
69
|
+
'class': 'economy'
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
if result.get('success'):
|
|
73
|
+
data = result.get('data', {})
|
|
74
|
+
log(f"ā
Emissions: {data.get('emissions_kg_co2e')} kg CO2e", 'GREEN')
|
|
75
|
+
log(f" Distance: {data.get('distance_km')} km", 'BLUE')
|
|
76
|
+
log(f" Per passenger: {data.get('emissions_per_passenger_kg_co2e')} kg CO2e", 'BLUE')
|
|
77
|
+
|
|
78
|
+
def demo_vehicle():
|
|
79
|
+
"""Demo: Calculate vehicle emissions"""
|
|
80
|
+
log('\nš Demo 3: Vehicle Emissions', 'CYAN')
|
|
81
|
+
log('Calculating emissions for 100 miles of driving...\n')
|
|
82
|
+
|
|
83
|
+
result = api_request('/v1/calculate/fuel', {
|
|
84
|
+
'fuel_type': 'gasoline',
|
|
85
|
+
'distance': 100,
|
|
86
|
+
'unit': 'miles',
|
|
87
|
+
'vehicle_type': 'car'
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
if result.get('success'):
|
|
91
|
+
data = result.get('data', {})
|
|
92
|
+
log(f"ā
Emissions: {data.get('emissions_kg_co2e')} kg CO2e", 'GREEN')
|
|
93
|
+
log(f" Fuel consumed: {data.get('fuel_consumed_liters')} liters", 'BLUE')
|
|
94
|
+
log(f" Emission factor: {data.get('emission_factor')} kg CO2e per liter", 'BLUE')
|
|
95
|
+
|
|
96
|
+
def interactive_mode():
|
|
97
|
+
"""Interactive custom calculation"""
|
|
98
|
+
log('\nš Custom Calculation', 'CYAN')
|
|
99
|
+
|
|
100
|
+
source = input('Enter emission source (electricity/gasoline/diesel/natural_gas): ').strip()
|
|
101
|
+
value = float(input('Enter value: '))
|
|
102
|
+
unit = input('Enter unit (kWh/liters/m3): ').strip()
|
|
103
|
+
|
|
104
|
+
log('\nCalculating...\n')
|
|
105
|
+
|
|
106
|
+
result = api_request('/v1/emissions/calculate', {
|
|
107
|
+
'source': source,
|
|
108
|
+
'value': value,
|
|
109
|
+
'unit': unit,
|
|
110
|
+
'country': 'US'
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
if result.get('success'):
|
|
114
|
+
data = result.get('data', {})
|
|
115
|
+
log(f"ā
Emissions: {data.get('emissions_kg_co2e')} kg CO2e", 'GREEN')
|
|
116
|
+
log(f" Source: {data.get('source')}", 'BLUE')
|
|
117
|
+
log(f" Scope: {data.get('scope')}", 'BLUE')
|
|
118
|
+
else:
|
|
119
|
+
log(f"ā Error: {result.get('error', 'Unknown error')}", 'YELLOW')
|
|
120
|
+
|
|
121
|
+
def main():
|
|
122
|
+
"""Main function"""
|
|
123
|
+
log('\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā', 'BOLD')
|
|
124
|
+
log('ā ZeroCarbon API - Quick Start Demo ā', 'BOLD')
|
|
125
|
+
log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n', 'BOLD')
|
|
126
|
+
|
|
127
|
+
log('Welcome! This demo shows how easy it is to calculate carbon emissions.', 'BLUE')
|
|
128
|
+
log('No API key needed for testing.\n', 'BLUE')
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
# Run pre-built demos
|
|
132
|
+
demo_electricity()
|
|
133
|
+
demo_flight()
|
|
134
|
+
demo_vehicle()
|
|
135
|
+
|
|
136
|
+
# Offer interactive mode
|
|
137
|
+
log('\n' + 'ā' * 60, 'BLUE')
|
|
138
|
+
answer = input('\nWant to try a custom calculation? (y/n): ')
|
|
139
|
+
|
|
140
|
+
if answer.lower() == 'y':
|
|
141
|
+
interactive_mode()
|
|
142
|
+
|
|
143
|
+
# Show next steps
|
|
144
|
+
log('\n' + 'ā' * 60, 'GREEN')
|
|
145
|
+
log('\nš That\'s it! You just calculated carbon emissions via API.', 'GREEN')
|
|
146
|
+
log('\nš Next Steps:', 'CYAN')
|
|
147
|
+
log(' 1. Get free API key: https://app.zerocarbon.codes/signup', 'BLUE')
|
|
148
|
+
log(' 2. Read docs: https://docs.zerocarbon.codes', 'BLUE')
|
|
149
|
+
log(' 3. View examples: https://github.com/zerocarbon/examples', 'BLUE')
|
|
150
|
+
log(' 4. Join Discord: https://discord.gg/zerocarbon', 'BLUE')
|
|
151
|
+
log('\nš” Install SDK: pip install zerocarbon', 'YELLOW')
|
|
152
|
+
log('\n' + 'ā' * 60 + '\n', 'GREEN')
|
|
153
|
+
|
|
154
|
+
except Exception as e:
|
|
155
|
+
log(f'\nā Error: {str(e)}', 'YELLOW')
|
|
156
|
+
log('\nFalling back to local demo mode...', 'BLUE')
|
|
157
|
+
|
|
158
|
+
# Fallback with mock data
|
|
159
|
+
log('\nš Electricity Demo (Mock Data)', 'CYAN')
|
|
160
|
+
log('ā
1,000 kWh ā 386.5 kg CO2e', 'GREEN')
|
|
161
|
+
log('\nāļø Flight Demo (Mock Data)', 'CYAN')
|
|
162
|
+
log('ā
SFO ā JFK ā 532 kg CO2e per passenger', 'GREEN')
|
|
163
|
+
log('\nš Vehicle Demo (Mock Data)', 'CYAN')
|
|
164
|
+
log('ā
100 miles ā 38.2 kg CO2e', 'GREEN')
|
|
165
|
+
|
|
166
|
+
if __name__ == '__main__':
|
|
167
|
+
main()
|
package/web-demo.html
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>ZeroCarbon API - Interactive Demo</title>
|
|
7
|
+
<style>
|
|
8
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
9
|
+
|
|
10
|
+
body {
|
|
11
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
12
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
13
|
+
min-height: 100vh;
|
|
14
|
+
display: flex;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
align-items: center;
|
|
17
|
+
padding: 20px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.container {
|
|
21
|
+
background: white;
|
|
22
|
+
border-radius: 16px;
|
|
23
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
|
24
|
+
max-width: 600px;
|
|
25
|
+
width: 100%;
|
|
26
|
+
padding: 40px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
h1 {
|
|
30
|
+
font-size: 28px;
|
|
31
|
+
color: #1a202c;
|
|
32
|
+
margin-bottom: 8px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.subtitle {
|
|
36
|
+
color: #718096;
|
|
37
|
+
margin-bottom: 32px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.demo-section {
|
|
41
|
+
margin-bottom: 24px;
|
|
42
|
+
padding: 20px;
|
|
43
|
+
background: #f7fafc;
|
|
44
|
+
border-radius: 8px;
|
|
45
|
+
border-left: 4px solid #667eea;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.demo-title {
|
|
49
|
+
font-size: 18px;
|
|
50
|
+
font-weight: 600;
|
|
51
|
+
color: #2d3748;
|
|
52
|
+
margin-bottom: 12px;
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
gap: 8px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.demo-description {
|
|
59
|
+
color: #718096;
|
|
60
|
+
margin-bottom: 16px;
|
|
61
|
+
font-size: 14px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
button {
|
|
65
|
+
background: #667eea;
|
|
66
|
+
color: white;
|
|
67
|
+
border: none;
|
|
68
|
+
padding: 12px 24px;
|
|
69
|
+
border-radius: 8px;
|
|
70
|
+
font-size: 14px;
|
|
71
|
+
font-weight: 600;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
transition: all 0.2s;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
button:hover {
|
|
77
|
+
background: #5a67d8;
|
|
78
|
+
transform: translateY(-1px);
|
|
79
|
+
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
:disabled {
|
|
83
|
+
background: #cbd5e0;
|
|
84
|
+
cursor: not-allowed;
|
|
85
|
+
transform: none;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.result {
|
|
89
|
+
margin-top: 16px;
|
|
90
|
+
padding: 16px;
|
|
91
|
+
background: white;
|
|
92
|
+
border-radius: 6px;
|
|
93
|
+
border: 1px solid #e2e8f0;
|
|
94
|
+
display: none;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.result.show {
|
|
98
|
+
display: block;
|
|
99
|
+
animation: slideIn 0.3s ease;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@keyframes slideIn {
|
|
103
|
+
from {
|
|
104
|
+
opacity: 0;
|
|
105
|
+
transform: translateY(-10px);
|
|
106
|
+
}
|
|
107
|
+
to {
|
|
108
|
+
opacity: 1;
|
|
109
|
+
transform: translateY(0);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.result-value {
|
|
114
|
+
font-size: 24px;
|
|
115
|
+
font-weight: 700;
|
|
116
|
+
color: #10b981;
|
|
117
|
+
margin-bottom: 8px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.result-detail {
|
|
121
|
+
color: #64748b;
|
|
122
|
+
font-size: 13px;
|
|
123
|
+
margin-top: 4px;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.code-block {
|
|
127
|
+
background: #1a202c;
|
|
128
|
+
color: #e2e8f0;
|
|
129
|
+
padding: 16px;
|
|
130
|
+
border-radius: 6px;
|
|
131
|
+
font-family: 'Monaco', 'Courier New', monospace;
|
|
132
|
+
font-size: 12px;
|
|
133
|
+
overflow-x: auto;
|
|
134
|
+
margin-top: 24px;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.next-steps {
|
|
138
|
+
margin-top: 32px;
|
|
139
|
+
padding: 20px;
|
|
140
|
+
background: #edf2f7;
|
|
141
|
+
border-radius: 8px;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.next-steps h3 {
|
|
145
|
+
font-size: 16px;
|
|
146
|
+
color: #2d3748;
|
|
147
|
+
margin-bottom: 12px;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.next-steps a {
|
|
151
|
+
display: block;
|
|
152
|
+
color: #667eea;
|
|
153
|
+
text-decoration: none;
|
|
154
|
+
margin: 8px 0;
|
|
155
|
+
font-size: 14px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.next-steps a:hover {
|
|
159
|
+
text-decoration: underline;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.loading {
|
|
163
|
+
display: inline-block;
|
|
164
|
+
width: 14px;
|
|
165
|
+
height: 14px;
|
|
166
|
+
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
167
|
+
border-top-color: white;
|
|
168
|
+
border-radius: 50%;
|
|
169
|
+
animation: spin 0.8s linear infinite;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@keyframes spin {
|
|
173
|
+
to { transform: rotate(360deg); }
|
|
174
|
+
}
|
|
175
|
+
</style>
|
|
176
|
+
</head>
|
|
177
|
+
<body>
|
|
178
|
+
<div class="container">
|
|
179
|
+
<h1>ā” ZeroCarbon API Demo</h1>
|
|
180
|
+
<p class="subtitle">Calculate carbon emissions in real-time. No signup required.</p>
|
|
181
|
+
|
|
182
|
+
<div class="demo-section">
|
|
183
|
+
<div class="demo-title">š Electricity Emissions</div>
|
|
184
|
+
<div class="demo-description">Calculate emissions from 1,000 kWh of U.S. electricity</div>
|
|
185
|
+
<button onclick="demoElectricity(this)">Run Demo</button>
|
|
186
|
+
<div class="result" id="result-electricity">
|
|
187
|
+
<div class="result-value"></div>
|
|
188
|
+
<div class="result-detail"></div>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
<div class="demo-section">
|
|
193
|
+
<div class="demo-title">āļø Flight Emissions</div>
|
|
194
|
+
<div class="demo-description">Calculate emissions for SFO ā JFK economy flight</div>
|
|
195
|
+
<button onclick="demoFlight(this)">Run Demo</button>
|
|
196
|
+
<div class="result" id="result-flight">
|
|
197
|
+
<div class="result-value"></div>
|
|
198
|
+
<div class="result-detail"></div>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
<div class="demo-section">
|
|
203
|
+
<div class="demo-title">š Vehicle Emissions</div>
|
|
204
|
+
<div class="demo-description">Calculate emissions for 100 miles of driving</div>
|
|
205
|
+
<button onclick="demoVehicle(this)">Run Demo</button>
|
|
206
|
+
<div class="result" id="result-vehicle">
|
|
207
|
+
<div class="result-value"></div>
|
|
208
|
+
<div class="result-detail"></div>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
|
|
212
|
+
<div class="code-block">
|
|
213
|
+
// It's this easy:<br>
|
|
214
|
+
const response = await fetch('https://api.zerocarbon.codes/v1/emissions/calculate', {<br>
|
|
215
|
+
method: 'POST',<br>
|
|
216
|
+
body: JSON.stringify({<br>
|
|
217
|
+
source: 'electricity',<br>
|
|
218
|
+
value: 1000,<br>
|
|
219
|
+
unit: 'kWh',<br>
|
|
220
|
+
country: 'US'<br>
|
|
221
|
+
})<br>
|
|
222
|
+
});
|
|
223
|
+
</div>
|
|
224
|
+
|
|
225
|
+
<div class="next-steps">
|
|
226
|
+
<h3>š Ready to integrate?</h3>
|
|
227
|
+
<a href="https://app.zerocarbon.codes/signup" target="_blank">ā Get Free API Key (30 seconds)</a>
|
|
228
|
+
<a href="https://docs.zerocarbon.codes" target="_blank">ā View Full Documentation</a>
|
|
229
|
+
<a href="https://github.com/zerocarbon/examples" target="_blank">ā See Example Applications</a>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
<script>
|
|
234
|
+
// Auto-detect API base URL
|
|
235
|
+
const API_BASE = window.location.hostname === 'localhost'
|
|
236
|
+
? 'http://localhost:3000/api'
|
|
237
|
+
: 'https://zerocarbon.codes/api';
|
|
238
|
+
|
|
239
|
+
async function apiRequest(endpoint, data) {
|
|
240
|
+
const response = await fetch(`${API_BASE}${endpoint}`, {
|
|
241
|
+
method: 'POST',
|
|
242
|
+
headers: { 'Content-Type': 'application/json' },
|
|
243
|
+
body: JSON.stringify(data)
|
|
244
|
+
});
|
|
245
|
+
return response.json();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function showResult(id, value, detail) {
|
|
249
|
+
const result = document.getElementById(id);
|
|
250
|
+
result.querySelector('.result-value').textContent = value;
|
|
251
|
+
result.querySelector('.result-detail').textContent = detail;
|
|
252
|
+
result.classList.add('show');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async function demoElectricity(button) {
|
|
256
|
+
button.disabled = true;
|
|
257
|
+
button.innerHTML = '<span class="loading"></span>';
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
const result = await apiRequest('/v1/emissions/calculate', {
|
|
261
|
+
source: 'electricity',
|
|
262
|
+
value: 1000,
|
|
263
|
+
unit: 'kWh',
|
|
264
|
+
country: 'US'
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
if (result.success) {
|
|
268
|
+
const emissions = result.data.emissions_kg_co2e;
|
|
269
|
+
showResult(
|
|
270
|
+
'result-electricity',
|
|
271
|
+
`${emissions} kg CO2e`,
|
|
272
|
+
`Equivalent to ${(emissions / 411).toFixed(1)} gallons of gasoline`
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
} catch (error) {
|
|
276
|
+
showResult('result-electricity', 'Error', error.message);
|
|
277
|
+
} finally {
|
|
278
|
+
button.disabled = false;
|
|
279
|
+
button.textContent = 'Run Demo';
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async function demoFlight(button) {
|
|
284
|
+
button.disabled = true;
|
|
285
|
+
button.innerHTML = '<span class="loading"></span>';
|
|
286
|
+
|
|
287
|
+
try {
|
|
288
|
+
const result = await apiRequest('/v1/calculate/flight', {
|
|
289
|
+
from: 'SFO',
|
|
290
|
+
to: 'JFK',
|
|
291
|
+
passengers: 1,
|
|
292
|
+
class: 'economy'
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
if (result.success) {
|
|
296
|
+
showResult(
|
|
297
|
+
'result-flight',
|
|
298
|
+
`${result.data.emissions_kg_co2e} kg CO2e`,
|
|
299
|
+
`Distance: ${result.data.distance_km} km ⢠Per passenger`
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
} catch (error) {
|
|
303
|
+
showResult('result-flight', 'Error', error.message);
|
|
304
|
+
} finally {
|
|
305
|
+
button.disabled = false;
|
|
306
|
+
button.textContent = 'Run Demo';
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async function demoVehicle(button) {
|
|
311
|
+
button.disabled = true;
|
|
312
|
+
button.innerHTML = '<span class="loading"></span>';
|
|
313
|
+
|
|
314
|
+
try {
|
|
315
|
+
const result = await apiRequest('/v1/calculate/fuel', {
|
|
316
|
+
fuel_type: 'gasoline',
|
|
317
|
+
distance: 100,
|
|
318
|
+
unit: 'miles',
|
|
319
|
+
vehicle_type: 'car'
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
if (result.success) {
|
|
323
|
+
showResult(
|
|
324
|
+
'result-vehicle',
|
|
325
|
+
`${result.data.emissions_kg_co2e} kg CO2e`,
|
|
326
|
+
`Fuel consumed: ${result.data.fuel_consumed_liters.toFixed(2)} liters`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
} catch (error) {
|
|
330
|
+
showResult('result-vehicle', 'Error', error.message);
|
|
331
|
+
} finally {
|
|
332
|
+
button.disabled = false;
|
|
333
|
+
button.textContent = 'Run Demo';
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
</script>
|
|
337
|
+
</body>
|
|
338
|
+
</html>
|