App.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. import React, { ChangeEvent } from "react";
  2. import "./App.css";
  3. import Headerbox from "./components/Headerbox";
  4. import { Person } from './interfaces/persons';
  5. import { Frequency } from "./interfaces/frequency";
  6. import { Type } from "./interfaces/type";
  7. import { WBS } from "./interfaces/wbs";
  8. import { WbsService } from "./service/wbsService";
  9. import { Income } from "./interfaces/incomes";
  10. interface AppState {
  11. personanzahl: number;
  12. persons: Person[];
  13. wbs: WBS;
  14. wbsResult: boolean;
  15. }
  16. const wbsService = new WbsService();
  17. class App extends React.Component<{}, AppState> {
  18. types: Array<Type> = [];
  19. freq: Array<Frequency> = [];
  20. constructor(props: {}) {
  21. super(props);
  22. this.state = {
  23. wbsResult: false,
  24. wbs: { wbsGranted: "Keinen", difference: 0, percent: 0, yearlyAmount: 0, yearlyAmountMax: 0 },
  25. personanzahl: 1,
  26. persons: [{ index: 1, incomes: [] as Income[], totalincome: 0 }]
  27. };
  28. wbsService.getTypes().then(types => {
  29. types.forEach(type => {
  30. this.types.push(type);
  31. });
  32. });
  33. wbsService.getFrequencies().then(freqs => {
  34. freqs.forEach(freq => {
  35. this.freq.push(freq);
  36. });
  37. });
  38. }
  39. render() {
  40. return (
  41. <div className="App" id="div_app">
  42. <h1 id="ueberschrift">WBS Rechner</h1>
  43. <Headerbox title="Haushaltsmitglieder">
  44. <div className="label-container">
  45. <label htmlFor="personenanzahl">Anzahl Personen im Haushalt</label>
  46. <input
  47. defaultValue={this.state.personanzahl}
  48. id="personenanzahl"
  49. type="number"
  50. min="1"
  51. max="20"
  52. onChange={this.updateInputValue}
  53. />
  54. </div>
  55. </Headerbox>
  56. {this.state.persons.map((p, pindex) =>
  57. <Headerbox title={'Daten der ' + p.index + '. Person'}>
  58. <div>
  59. {this.state.persons[p.index - 1].incomes.map((i, inindex) =>
  60. <div className="label_box">
  61. <div className="label-container">
  62. <label htmlFor={'type' + p.index + '_' + inindex}>Typ</label>
  63. <select id={'type_' + p.index + '_' + inindex} defaultValue={i.type} onChange={this.updateIncomeSelectValue}>
  64. <option id={'type_' + p.index + '_' + inindex + '_0'} value={0} disabled>keine Auswahl</option>
  65. {this.types.map(t =>
  66. <option id={'type' + p.index + '_' + inindex + '_' + t.value} value={t.value}> {t.description}</option>
  67. )}
  68. </select>
  69. </div>
  70. <div className="label-container">
  71. <label htmlFor={'frequency' + p.index + '_' + inindex}>Frequenz</label>
  72. <select id={'frequency_' + p.index + '_' + inindex} onChange={this.updateIncomeSelectValue} defaultValue={i.frequency} >
  73. <option id={'frequency_' + p.index + '_' + inindex + '_0'} value={0} disabled>keine Auswahl</option>
  74. {this.freq.map(f =>
  75. <option id={'frequency_' + p.index + '_' + inindex + '_' + f.value} value={f.value}> {f.description}</option>
  76. )}
  77. </select>
  78. </div>
  79. <div className="label-container">
  80. <label htmlFor={'amount_' + p.index + '_' + inindex}>Brutto Betrag</label>
  81. <input id={'amount_' + p.index + '_' + inindex} type="number" defaultValue={i.amount} onChange={this.updateIncomeValue} min={0} />
  82. </div>
  83. <div className="label-container">
  84. <label htmlFor={'advertisingCosts_' + p.index + '_' + inindex}>jährliche Werbungskosten</label>
  85. <input id={'advertisingCosts_' + p.index + '_' + inindex} type="number" defaultValue={i.advertisingCosts} onChange={this.updateIncomeValue} min={0} />
  86. </div>
  87. <div className="label-container">
  88. <label htmlFor={'delete_' + p.index + '_' + inindex}>Löschen</label>
  89. <button className="delete-button" id={'delete_' + p.index + '_' + inindex} onClick={() => this.deleteIncome(pindex, inindex)} title={(inindex + 1) + ' Einkommen der ' + p.index + ' Person löschen'} >&times; Löschen</button>
  90. </div>
  91. </div>
  92. )}
  93. <button onClick={() => this.addIncome(p.index)} className="calculateButton">+ Einkommen hinzufügen</button>
  94. </div>
  95. </Headerbox>
  96. )
  97. }
  98. <Headerbox title="WBS berechnen">
  99. <h2>Zusammenfassung Haushalt</h2>
  100. {this.state.persons.map(p =>
  101. <div className="label_box">
  102. <div className='label-container'>
  103. <label htmlFor={"nr" + p.index}>Nr.</label>
  104. <span id={"nr" + p.index}>{p.index}</span>
  105. </div>
  106. <div className="label-container">
  107. <label htmlFor={"kindsalter" + p.index}>Kindsalter</label>
  108. <span id={"kindsalter" + p.index}>N/A</span>
  109. </div>
  110. <div className="label-container">
  111. <label htmlFor={"freibetrage" + p.index}>Freibeträge</label>
  112. <span id={"freibetrage" + p.index}>N/A</span>
  113. </div>
  114. <div className="label-container">
  115. <label htmlFor={"gesamteinkommen" + p.index}>Gesamteinkommen</label>
  116. <span id={"gesamteinkommen" + p.index}>{p.totalincome}</span>
  117. </div>
  118. </div>
  119. )}
  120. <button onClick={this.calculateWBS.bind(this)} className="calculateButton">⚙ WBS berechnen</button>
  121. {this.state.wbsResult ?
  122. <div>
  123. <div className="label-container">
  124. <label htmlFor="yearlyAmount">anrechenbares jährliches Gesamteinkommen:</label>
  125. <span id="yearlyAmount">{this.state.wbs.yearlyAmount} €</span>
  126. </div>
  127. <div className="label-container">
  128. <label htmlFor="yearlyAmountMax">Einkommensgrenze:</label>
  129. <span id="yearlyAmountMax">{this.state.wbs.yearlyAmountMax} €</span>
  130. </div>
  131. <div className="label-container">
  132. <label htmlFor="difference">{this.state.wbs.difference > 0 ? 'Überschreitung' : 'Unterschreitung'}</label>
  133. <span id="difference">{this.state.wbs.difference} €</span>
  134. </div>
  135. <div className="label-container">
  136. <label htmlFor="percent">Verhältnis Gesamteinkommen / Einkommensgrenze</label>
  137. <span id="percent">{this.state.wbs.percent} %</span>
  138. </div>
  139. <div className="label-container">
  140. <label htmlFor="percent">Möglicher WBS:</label>
  141. <span id="percent">{this.state.wbs.wbsGranted}</span>
  142. </div>
  143. </div>
  144. :
  145. <div></div>
  146. }
  147. </Headerbox>
  148. </div >
  149. );
  150. }
  151. updateInputValue = (evt: ChangeEvent<HTMLInputElement>) => {
  152. this.setState({ personanzahl: evt.target.valueAsNumber });
  153. this.refreshPeople(evt.target.valueAsNumber);
  154. }
  155. updateIncomeValue = (evt: ChangeEvent<HTMLInputElement>) => {
  156. this.updateValueState(evt.target.id, evt.target.valueAsNumber);
  157. }
  158. updateIncomeSelectValue = (evt: ChangeEvent<HTMLSelectElement>) => {
  159. this.updateValueState(evt.target.id, evt.target.value);
  160. }
  161. updateValueState(id: string, value: any) {
  162. var parts = id.split("_");
  163. var field = parts[0];
  164. var personid: number = parseInt(parts[1]);
  165. var incomeId: number = parseInt(parts[2]);
  166. this.setState(prevState => {
  167. const persons = [...prevState.persons];
  168. const person = persons[personid - 1];
  169. const income = person.incomes[incomeId];
  170. if (field === "amount") {
  171. income.amount = value;
  172. person.totalincome = this.calculateTotalIncome(personid - 1);
  173. } else if (field === "advertisingCosts") {
  174. income.advertisingCosts = value;
  175. person.totalincome = this.calculateTotalIncome(personid - 1);
  176. } else if (field === "frequency") {
  177. income.frequency = value;
  178. person.totalincome = this.calculateTotalIncome(personid - 1);
  179. } else if (field === "type") {
  180. income.type = value;
  181. }
  182. return { persons };
  183. });
  184. }
  185. calculateWBS() {
  186. var persons: Array<Person> = this.state.persons;
  187. wbsService.calculateWbs(persons).then(wbsErg => {
  188. this.setState({ wbsResult: true });
  189. this.setState({ wbs: wbsErg });
  190. });
  191. }
  192. calculateTotalIncome(personindex: number): number {
  193. let totalIncome = 0;
  194. for (const income of this.state.persons[personindex].incomes) {
  195. totalIncome += ((income.frequency * income.amount) - income.advertisingCosts);
  196. }
  197. return totalIncome;
  198. }
  199. refreshPeople(personenanzahl: number) {
  200. if (personenanzahl > this.state.persons.length) {
  201. let anzahl = personenanzahl - this.state.persons.length;
  202. for (let i = 1; i <= anzahl; i++) {
  203. this.addPerson();
  204. }
  205. }
  206. if (personenanzahl < this.state.persons.length) {
  207. let anzahl = this.state.persons.length - personenanzahl;
  208. for (let i = 1; i <= anzahl; i++) {
  209. this.deletePerson(this.state.persons.length);
  210. }
  211. }
  212. }
  213. addPerson() {
  214. const newPerson: Person = {
  215. index: this.getHighestIndex(this.state.persons) + 1,
  216. incomes: [],
  217. totalincome: 0
  218. };
  219. this.setState(prevState => ({
  220. persons: [...prevState.persons, newPerson]
  221. }));
  222. }
  223. deletePerson(index: number) {
  224. this.setState(prevState => ({
  225. persons: prevState.persons.filter(person => person.index !== index)
  226. }));
  227. }
  228. deleteIncome(pindex: number, iindex: number) {
  229. console.log(pindex + " - " + iindex);
  230. this.setState(prevState => {
  231. const persons = [...prevState.persons];
  232. const person = persons[pindex];
  233. console.log(person.incomes);
  234. person.incomes.splice(iindex, 1)
  235. console.log(person.incomes);
  236. person.totalincome = this.calculateTotalIncome(pindex);
  237. return { persons };
  238. });
  239. console.log(this.state.persons);
  240. }
  241. addIncome(index: number) {
  242. const newincome = {
  243. index: this.getHighestIndex(this.state.persons[index - 1].incomes) + 1,
  244. amount: 0,
  245. frequency: 0,
  246. advertisingCosts: 0,
  247. type: 0
  248. };
  249. this.setState(prevState => {
  250. const persons = [...prevState.persons];
  251. const person = persons[index - 1];
  252. person.incomes = [...person.incomes, newincome];
  253. return { persons };
  254. });
  255. }
  256. getHighestIndex(arr: any[]) {
  257. let highestIndex = 0;
  258. if (typeof arr === "undefined") {
  259. return highestIndex;
  260. }
  261. for (const item of arr) {
  262. if (item.index > highestIndex) {
  263. highestIndex = item.index;
  264. }
  265. }
  266. return highestIndex;
  267. }
  268. }
  269. export default App;