If forms in the select viewer have the same name, append a counter.
[ustaxviewer.git] / src / TaxReturnView.tsx
1 // Copyright 2020 Blue Static <https://www.bluestatic.org>
2 // This program is free software licensed under the GNU General Public License,
3 // version 3.0. The full text of the license can be found in LICENSE.txt.
4 // SPDX-License-Identifier: GPL-3.0-only
5
6 import { createEffect, createMemo, createState } from 'solid-js';
7 import { For } from 'solid-js/dom';
8 import { Form, Person, TaxReturn } from 'ustaxlib/core';
9
10 import FormView from './FormView';
11
12 const S = require('./TaxReturnView.css');
13
14 export interface Props {
15 tr: TaxReturn;
16 showForm?: string;
17 onFormChange?: (formName: string) => void;
18 }
19
20 function hashifyFormName(name: string): string {
21 return '#' + name.replace(/[^\w]+/g, '_');
22 }
23
24 export default function TaxReturnView(props: Props) {
25 const [ state, setState ] = createState({ form: props.tr.forms[0] });
26
27 const changeForm = e => {
28 setState({ form: props.tr.forms[e.target.value] });
29 if (props.onFormChange)
30 props.onFormChange(hashifyFormName(e.target.selectedOptions[0].textContent));
31 };
32
33 const formIndexToName = createMemo(() => {
34 const formNameCounts = {};
35 let forms = props.tr.forms.map((form, i) => {
36 let name = form.name;
37 const person = form.person();
38 if (person !== undefined) {
39 const personName = person === Person.joint ? 'Joint' : person.name;
40 name += ` (${personName})`;
41 }
42 if (name in formNameCounts) {
43 formNameCounts[name] += 1;
44 name += ` (${formNameCounts[name]})`;
45 } else {
46 formNameCounts[name] = 1;
47 }
48 return [i, name];
49 });
50 forms.sort((a, b) => {
51 if (a[1] < b[1])
52 return -1;
53 if (a[1] > b[1])
54 return 1;
55 return 0;
56 });
57 return forms;
58 });
59
60 createEffect(() => {
61 if (props.showForm) {
62 for (let f of formIndexToName()) {
63 if (hashifyFormName(f[1] as string) === props.showForm) {
64 setState({ form: props.tr.forms[f[0]] });
65 }
66 }
67 }
68 });
69
70 const formSelector = (
71 <select onchange={changeForm}>
72 <For each={formIndexToName()}>
73 {tuple => (<option value={tuple[0]} selected={state.form === props.tr.forms[tuple[0]]}>{tuple[1]}</option>)}
74 </For>
75 </select>
76 );
77
78 return (
79 <div>
80 <div class={S.header}>
81 <h1>ustaxlib Federal {props.tr.year}</h1>
82 {formSelector}
83 </div>
84
85 <FormView tr={props.tr} form={state.form as Form<any>} />
86 </div>
87 );
88 }
89