Simple PHP & SQL weight tracker for multiple persons
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <html lang="en">
  2. <head>
  3. <meta charset="utf-8" />
  4. <title>Weight-Track</title>
  5. <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.0/dist/Chart.bundle.min.js" integrity="sha256-tSYaQkuUF17Z5HozxXRWckY1j6uVLYFEHGEooJ6YsP0=" crossorigin="anonymous"></script>
  6. </head>
  7. <body>
  8. <div id="content">
  9. <h1>Weight-Track</h1>
  10. <p id="status">Please wait while Weight-Track is loading... (JavaScript needed)</p>
  11. </div>
  12. <div id="footer">
  13. <p>Made with <a href="https://www.chartjs.org/docs/latest/">Chart.js</a></p>
  14. </div>
  15. <script type="text/javascript">
  16. var colorFromIndex = function(index) {
  17. var colors = [
  18. '129, 38, 204',
  19. '48, 181, 36',
  20. '255, 99, 132',
  21. '54, 162, 235',
  22. '255, 206, 86',
  23. '75, 192, 192',
  24. '153, 102, 255',
  25. '255, 159, 64'
  26. ];
  27. if (index < colors.length) {
  28. return colors[index];
  29. } else {
  30. return '120, 120, 120';
  31. }
  32. };
  33. var createDataset = function(name, data, color, id) {
  34. return {
  35. label: name,
  36. data: data,
  37. yAxisID: id,
  38. backgroundColor: [
  39. 'rgba(' + color + ', 0)'
  40. ],
  41. borderColor: [
  42. 'rgba(' + color + ', 1)'
  43. ],
  44. pointBorderColor: 'rgba(' + color + ', 1)',
  45. pointRadius: 2,
  46. borderWidth: 4
  47. };
  48. };
  49. var addToForm = function(form, element, name) {
  50. var fe = document.createElement('p');
  51. fe.innerHTML = name + ' ';
  52. fe.appendChild(element);
  53. form.appendChild(fe);
  54. };
  55. var renderUser = function(data) {
  56. var div = document.createElement('div');
  57. var ctx = document.createElement('canvas');
  58. var min_date = new Date('3000-01-01T00:00:00');
  59. var max_date = new Date('1000-01-01T00:00:00');
  60. var min_kilo = 1000;
  61. var max_kilo = 0;
  62. for (var i = 0; i < data.users.length; i++) {
  63. for (var j = 0; j < data.users[i].data.length; j++) {
  64. temp_date = new Date(data.users[i].data[j].x);
  65. temp_kilo = parseInt(data.users[i].data[j].y);
  66. if (temp_date < min_date) {
  67. min_date = temp_date;
  68. }
  69. if (temp_date > max_date) {
  70. max_date = temp_date;
  71. }
  72. if (temp_kilo < min_kilo) {
  73. min_kilo = temp_kilo;
  74. }
  75. if (temp_kilo > max_kilo) {
  76. max_kilo = temp_kilo;
  77. }
  78. }
  79. }
  80. var days = (max_date - min_date) / 1000 / 60 / 60 / 24;
  81. var pixels_per_day = 3000 / 365;
  82. var width_px = days * pixels_per_day;
  83. var kilos = (max_kilo - min_kilo);
  84. var pixels_per_kilo = 1400 / 100;
  85. var height_px = kilos * pixels_per_kilo;
  86. var datasets = [];
  87. for (var i = 0; i < data.users.length; i++) {
  88. for (var j = 0; j <= 1; j++) {
  89. var set = createDataset(data.users[i].name,
  90. data.users[i].data, colorFromIndex(i), j ? 'A' : 'B');
  91. datasets.push(set);
  92. }
  93. }
  94. var chart = new Chart(ctx, {
  95. type: 'line',
  96. data: {
  97. datasets: datasets
  98. },
  99. options: {
  100. maintainAspectRatio: false,
  101. scales: {
  102. xAxes: [{
  103. type: 'time',
  104. time: {
  105. unit: 'day'
  106. }
  107. }],
  108. yAxes: [{
  109. id: 'A',
  110. type: 'linear',
  111. position: 'left'
  112. }, {
  113. id: 'B',
  114. type: 'linear',
  115. position: 'right'
  116. }]
  117. },
  118. events: [
  119. 'mousemove', 'mouseout', 'click',
  120. 'touchstart', 'touchmove', 'touchend'
  121. ],
  122. tooltips: {
  123. mode: 'nearest',
  124. intersect: false,
  125. axis: 'xy'
  126. }
  127. }
  128. });
  129. if (data.users.length > 0) {
  130. div_wrapper = document.createElement('div');
  131. div_wrapper.setAttribute('style', 'width: ' + Math.ceil(width_px) + 'px;');
  132. div_wrapper.style.width = Math.ceil(width_px) + 'px';
  133. div_wrapper.style.height = height_px + 'px';
  134. div_wrapper.width = Math.ceil(width_px);
  135. div_wrapper.height = height_px;
  136. div_wrapper.appendChild(ctx);
  137. div_wrapper2 = document.createElement('div');
  138. div_wrapper2.setAttribute('style', 'overflow-x: auto; overflow-y: auto;');
  139. div_wrapper2.appendChild(div_wrapper);
  140. div.appendChild(div_wrapper2);
  141. div.appendChild(document.createElement('hr'));
  142. var date = new Date();
  143. var hours = date.getHours();
  144. hours = (hours < 10) ? '0' + hours : hours;
  145. var minutes = date.getMinutes();
  146. minutes = (minutes < 10) ? '0' + minutes : minutes;
  147. var form_append = document.createElement('form');
  148. form_append.setAttribute('method', 'post');
  149. form_append.setAttribute('action', 'weight.php');
  150. var p_append = document.createElement('p');
  151. p_append.innerHTML = 'Add new Data-Point:';
  152. form_append.appendChild(p_append);
  153. var name_append = document.createElement('select');
  154. for (var i = 0; i < data.users.length; i++) {
  155. var option = document.createElement('option');
  156. option.text = data.users[i].name;
  157. option.value = 'user_' + data.users[i].id;
  158. name_append.add(option);
  159. }
  160. name_append.setAttribute('name', 'username');
  161. name_append.required = true;
  162. addToForm(form_append, name_append, 'Username:');
  163. var date_append = document.createElement('input');
  164. date_append.setAttribute('type', 'date');
  165. date_append.setAttribute('name', 'date');
  166. date_append.setAttribute('placeholder', 'Date');
  167. date_append.required = true;
  168. date_append.value = date.toISOString().slice(0, 10);
  169. addToForm(form_append, date_append, 'Date:');
  170. var time_append = document.createElement('input');
  171. time_append.setAttribute('type', 'time');
  172. time_append.setAttribute('name', 'time');
  173. time_append.setAttribute('placeholder', 'Time');
  174. time_append.required = true;
  175. time_append.value = hours + ':' + minutes;
  176. addToForm(form_append, time_append, 'Time:');
  177. var weight_append = document.createElement('input');
  178. weight_append.setAttribute('type', 'number');
  179. weight_append.setAttribute('name', 'weight');
  180. weight_append.setAttribute('step', '0.1');
  181. weight_append.min = 42.0;
  182. weight_append.max = 999.9;
  183. weight_append.setAttribute('placeholder', 'Weight');
  184. weight_append.required = true;
  185. addToForm(form_append, weight_append, 'Weight:');
  186. var submit_append = document.createElement('input');
  187. submit_append.setAttribute('type', 'submit');
  188. submit_append.setAttribute('value', 'Add Data');
  189. form_append.appendChild(submit_append);
  190. div.appendChild(form_append);
  191. div.appendChild(document.createElement('hr'));
  192. }
  193. var form_new = document.createElement('form');
  194. form_new.setAttribute('method', 'post');
  195. form_new.setAttribute('action', 'weight.php');
  196. var p_new = document.createElement('p');
  197. p_new.innerHTML = 'Add new User:';
  198. form_new.appendChild(p_new);
  199. var name_new = document.createElement('input');
  200. name_new.setAttribute('type', 'text');
  201. name_new.setAttribute('name', 'username');
  202. name_new.setAttribute('placeholder', 'Name');
  203. name_new.required = true;
  204. addToForm(form_new, name_new, 'Username:');
  205. var submit_new = document.createElement('input');
  206. submit_new.setAttribute('type', 'submit');
  207. submit_new.setAttribute('value', 'Add User');
  208. form_new.appendChild(submit_new);
  209. div.appendChild(form_new);
  210. div.appendChild(document.createElement('hr'));
  211. document.getElementById("content").appendChild(div);
  212. };
  213. var getJSON = function(url, callback) {
  214. var xhr = new XMLHttpRequest();
  215. xhr.open('GET', url, true);
  216. xhr.responseType = 'json';
  217. xhr.onload = function() {
  218. if (xhr.status === 200) {
  219. callback(null, xhr.response);
  220. } else {
  221. callback(xhr.status, xhr.response);
  222. }
  223. };
  224. xhr.send();
  225. };
  226. document.getElementById("status").textContent = "Loading from Database...";
  227. getJSON('weight.php', function(err, data) {
  228. if (err !== null) {
  229. document.getElementById("status").textContent = 'Error: ' + err;
  230. return;
  231. }
  232. if (typeof data.error !== 'undefined') {
  233. document.getElementById("status").textContent = 'Error: ' + data.error;
  234. return;
  235. }
  236. if (typeof data.users !== 'undefined') {
  237. var s = 'Received data for ' + data.users.length + ' users';
  238. if (data.users.length > 0) {
  239. s += ': ';
  240. for (var i = 0; i < data.users.length; i++) {
  241. s += '"' + data.users[i].name + '"';
  242. if (i < (data.users.length - 1)) {
  243. s += ', ';
  244. }
  245. }
  246. s += '. Rendering...';
  247. } else {
  248. s += '. Nothing to show!';
  249. }
  250. document.getElementById("status").textContent = s;
  251. renderUser(data);
  252. } else {
  253. document.getElementById("status").textContent = 'Error: no data';
  254. return;
  255. }
  256. });
  257. </script>
  258. </body>
  259. </html>