Skip to content

Commit bb0d82d

Browse files
authored
Merge pull request #5 from ceotjoe/DEV
Added usage stats
2 parents 28ab8c9 + 9dc88b7 commit bb0d82d

5 files changed

Lines changed: 163 additions & 7 deletions

File tree

app.js

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,36 @@ function formatTime(seconds) {
117117
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
118118
}
119119

120+
// Function to record usage data
121+
function recordUsage(deviceName, currentMa, duration, volume, ppm) {
122+
const now = new Date();
123+
const date = now.toLocaleDateString();
124+
const time = now.toLocaleTimeString();
125+
const usage = { date, time, device: deviceName, currentMa, duration, volume, ppm };
126+
127+
let stats = JSON.parse(localStorage.getItem('usageStats')) || [];
128+
stats.push(usage);
129+
localStorage.setItem('usageStats', JSON.stringify(stats));
130+
}
131+
132+
// Updated calculateTime to record usage
120133
function calculateTime() {
121-
const currentMa = parseFloat(document.getElementById('device').value) || 0; // Current in mA from dropdown
122-
const volumeMl = parseFloat(document.getElementById('volume').value) || 0; // Volume in mL
134+
const deviceSelect = document.getElementById('device');
135+
const currentMa = parseFloat(deviceSelect.value) || 0;
136+
const volumeMl = parseFloat(document.getElementById('volume').value) || 0;
123137
const desiredPpm = parseFloat(document.getElementById('desiredPpm').value) || 0;
124138

125139
if (currentMa > 0 && volumeMl > 0 && desiredPpm > 0) {
126-
const current = currentMa / 1000; // mA to A
127-
const volume = volumeMl / 1000; // mL to L
140+
const current = currentMa / 1000; // Convert mA to A
141+
const volume = volumeMl / 1000; // Convert mL to L
128142
timeInSeconds = (desiredPpm * volume * z * faradayConstant) / (1000 * current * molarMassSilver);
129143
remainingTime = timeInSeconds;
130-
updateUIText({ time: formatTime(timeInSeconds) });
144+
const duration = formatTime(timeInSeconds);
145+
updateUIText({ time: duration });
146+
147+
// Record the usage
148+
const deviceName = deviceSelect.options[deviceSelect.selectedIndex].text.split(' (')[0];
149+
recordUsage(deviceName, currentMa, duration, volumeMl, desiredPpm);
131150
} else {
132151
alert(translations.error);
133152
}
@@ -218,6 +237,65 @@ function handleServiceWorkerUpdates() {
218237
}
219238
}
220239

240+
// Function to show the statistics screen
241+
function showStatistics() {
242+
const statsContainer = document.getElementById('statistics');
243+
const mainContainer = document.querySelector('.container');
244+
mainContainer.style.display = 'none';
245+
statsContainer.style.display = 'block';
246+
247+
const statsBody = document.getElementById('statsBody');
248+
statsBody.innerHTML = '';
249+
250+
const stats = JSON.parse(localStorage.getItem('usageStats')) || [];
251+
stats.forEach(stat => {
252+
const row = document.createElement('tr');
253+
row.innerHTML = `
254+
<td>${stat.date}</td>
255+
<td>${stat.time}</td>
256+
<td>${stat.device}</td>
257+
<td>${stat.currentMa}</td>
258+
<td>${stat.duration}</td>
259+
<td>${stat.volume}</td>
260+
<td>${stat.ppm}</td>
261+
`;
262+
statsBody.appendChild(row);
263+
});
264+
}
265+
266+
// Function to hide the statistics screen
267+
function hideStatistics() {
268+
const statsContainer = document.getElementById('statistics');
269+
const mainContainer = document.querySelector('.container');
270+
statsContainer.style.display = 'none';
271+
mainContainer.style.display = 'block';
272+
}
273+
274+
// Function to export statistics as CSV
275+
function exportCSV() {
276+
const stats = JSON.parse(localStorage.getItem('usageStats')) || [];
277+
if (stats.length === 0) {
278+
alert(translations.noData);
279+
return;
280+
}
281+
282+
const headers = 'Date,Time,Device,Current (mA),Duration (hh:mm:ss),Volume (mL),PPM\n';
283+
const csvRows = stats.map(stat =>
284+
`${stat.date},${stat.time},${stat.device},${stat.currentMa},${stat.duration},${stat.volume},${stat.ppm}`
285+
);
286+
const csvContent = headers + csvRows.join('\n');
287+
288+
const blob = new Blob([csvContent], { type: 'text/csv' });
289+
const url = URL.createObjectURL(blob);
290+
const a = document.createElement('a');
291+
a.href = url;
292+
a.download = 'SilverTimer_Usage_Statistics.csv';
293+
document.body.appendChild(a);
294+
a.click();
295+
document.body.removeChild(a);
296+
URL.revokeObjectURL(url);
297+
}
298+
221299
// Initialize with translations, devices, and SW update handling
222300
window.onload = () => {
223301
loadTranslationsAndDevices();

index.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ <h2 data-i18n="appTitle">SilverTimer</h2>
2020
<div id="result" data-i18n="result" data-i18n-params="time:00:00:00">Time: 00:00:00</div>
2121
<button onclick="startTimer()" id="startBtn" data-i18n="startBtn"></button>
2222
<button onclick="stopTimer()" id="stopBtn" disabled data-i18n="stopBtn"></button>
23+
<button onclick="showStatistics()" data-i18n="statsBtn">Statistics</button>
2324
<div id="timer" data-i18n="timer" data-i18n-params="time:00:00:00">Remaining: 00:00:00</div>
2425
<footer>
2526
<a href="https://github.com/ceotjoe/SilverTimer_PWA/blob/main/README.md" target="_blank" data-i18n="readmeLink">Readme</a>
@@ -34,6 +35,26 @@ <h3 data-i18n="modalTitle"></h3>
3435
</div>
3536
</div>
3637

38+
<div id="statistics" class="stats-container" style="display: none;">
39+
<h2 data-i18n="statsTitle">Usage Statistics</h2>
40+
<table id="statsTable">
41+
<thead>
42+
<tr>
43+
<th data-i18n="date">Date</th>
44+
<th data-i18n="time">Time</th>
45+
<th data-i18n="device">Device</th>
46+
<th data-i18n="current">Current (mA)</th>
47+
<th data-i18n="duration">Duration (hh:mm:ss)</th>
48+
<th data-i18n="volume">Volume (mL)</th>
49+
<th data-i18n="ppm">PPM</th>
50+
</tr>
51+
</thead>
52+
<tbody id="statsBody"></tbody>
53+
</table>
54+
<button onclick="exportCSV()" data-i18n="exportBtn">Export to CSV</button>
55+
<button onclick="hideStatistics()" data-i18n="backBtn">Back</button>
56+
</div>
57+
3758
<script src="/SilverTimer_PWA/app.js"></script>
3859
<script>
3960
if ('serviceWorker' in navigator) {

locales/de.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,17 @@
1212
"modalText": "Die gewünschte Silber-PPM wurde erreicht.",
1313
"modalBtn": "Alarm Stoppen",
1414
"error": "Bitte wählen Sie ein Gerät und geben Sie gültige positive Zahlen für Volumen und PPM ein.",
15-
"readmeLink": "Liesmich"
15+
"readmeLink": "Liesmich",
16+
"statsBtn": "Statistiken",
17+
"statsTitle": "Nutzungsstatistiken",
18+
"date": "Datum",
19+
"time": "Uhrzeit",
20+
"device": "Gerät",
21+
"current": "Strom (mA)",
22+
"duration": "Dauer (hh:mm:ss)",
23+
"volume": "Volumen (mL)",
24+
"ppm": "PPM",
25+
"exportBtn": "Als CSV exportieren",
26+
"backBtn": "Zurück",
27+
"noData": "Keine Nutzungsdaten vorhanden."
1628
}

locales/en.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,17 @@
1212
"modalText": "The desired silver PPM has been achieved.",
1313
"modalBtn": "Stop Alarm",
1414
"error": "Please select a device and enter valid positive numbers for volume and PPM.",
15-
"readmeLink": "Readme"
15+
"readmeLink": "Readme",
16+
"statsBtn": "Statistics",
17+
"statsTitle": "Usage Statistics",
18+
"date": "Date",
19+
"time": "Time",
20+
"device": "Device",
21+
"current": "Current (mA)",
22+
"duration": "Duration (hh:mm:ss)",
23+
"volume": "Volume (mL)",
24+
"ppm": "PPM",
25+
"exportBtn": "Export to CSV",
26+
"backBtn": "Back",
27+
"noData": "No usage data available."
1628
}

styles.css

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,29 @@ footer a:hover {
7272
border-radius: 8px;
7373
text-align: center;
7474
}
75+
.stats-container {
76+
background: white;
77+
padding: 20px;
78+
border-radius: 8px;
79+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
80+
width: 100%;
81+
max-width: 600px;
82+
text-align: center;
83+
margin: 20px auto;
84+
}
85+
table {
86+
width: 100%;
87+
border-collapse: collapse;
88+
margin-bottom: 20px;
89+
}
90+
th, td {
91+
padding: 8px;
92+
border: 1px solid #ddd;
93+
text-align: left;
94+
}
95+
th {
96+
background-color: #f4f4f4;
97+
}
7598

7699
/* Dark Mode */
77100
@media (prefers-color-scheme: dark) {
@@ -103,4 +126,14 @@ footer a:hover {
103126
.modal-content {
104127
background: #2a2a2a;
105128
}
129+
.stats-container {
130+
background: #2a2a2a;
131+
box-shadow: 0 2px 10px rgba(255,255,255,0.1);
132+
}
133+
th, td {
134+
border-color: #555;
135+
}
136+
th {
137+
background-color: #333;
138+
}
106139
}

0 commit comments

Comments
 (0)