From b9bf00acc2ca449935161c74f2cb041e2f440f6a Mon Sep 17 00:00:00 2001 From: teddy Date: Tue, 2 Apr 2024 10:30:42 +0100 Subject: [PATCH] Initial commit. Functional approach --- package-lock.json | 39 +++ package.json | 1 + src/App.js | 25 -- src/App.jsx | 59 ++++ src/{App.test.js => App.test.jsx} | 0 src/Logo.png | Bin 0 -> 14273 bytes src/PageHome.jsx | 22 ++ src/components/BlockFormSection.jsx | 25 ++ .../ContentFormInvoiceOrEstimate.jsx | 176 ++++++++++ src/components/ControlsFillDefaults.jsx | 113 ++++++ src/components/Input.jsx | 51 +++ src/components/MainContentForm.jsx | 175 ++++++++++ src/components/MainContentForm_functional.jsx | 322 ++++++++++++++++++ src/components/MethodsInput.jsx | 20 ++ src/config.js | 77 +++++ src/download.png | Bin 0 -> 21953 bytes src/index.css | 144 +++++++- src/index.html | 2 + src/logo192.png | Bin 0 -> 14273 bytes 19 files changed, 1225 insertions(+), 26 deletions(-) delete mode 100644 src/App.js create mode 100644 src/App.jsx rename src/{App.test.js => App.test.jsx} (100%) create mode 100644 src/Logo.png create mode 100644 src/PageHome.jsx create mode 100644 src/components/BlockFormSection.jsx create mode 100644 src/components/ContentFormInvoiceOrEstimate.jsx create mode 100644 src/components/ControlsFillDefaults.jsx create mode 100644 src/components/Input.jsx create mode 100644 src/components/MainContentForm.jsx create mode 100644 src/components/MainContentForm_functional.jsx create mode 100644 src/components/MethodsInput.jsx create mode 100644 src/config.js create mode 100644 src/download.png create mode 100644 src/index.html create mode 100644 src/logo192.png diff --git a/package-lock.json b/package-lock.json index e239c10..f8bde55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router-dom": "^6.22.3", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" } @@ -3352,6 +3353,14 @@ } } }, + "node_modules/@remix-run/router": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", + "integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -15074,6 +15083,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz", + "integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==", + "dependencies": { + "@remix-run/router": "1.15.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.22.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz", + "integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==", + "dependencies": { + "@remix-run/router": "1.15.3", + "react-router": "6.22.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", diff --git a/package.json b/package.json index e74f9ca..b46d741 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "@testing-library/user-event": "^13.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-router-dom": "^6.22.3", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, diff --git a/src/App.js b/src/App.js deleted file mode 100644 index 3784575..0000000 --- a/src/App.js +++ /dev/null @@ -1,25 +0,0 @@ -import logo from './logo.svg'; -import './App.css'; - -function App() { - return ( -
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - -
-
- ); -} - -export default App; diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..b0dd998 --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,59 @@ +import imageLogo from './Logo.png'; + +import './App.css'; + +import React from 'react'; +import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom'; +import PageHome from './PageHome'; +import InputWrapped from './components/Input'; +import methods from './components/MethodsInput'; +// const makeInputJSON = methods.makeInputJSON; +const makeInputJSON = (dictArgs) => { + return methods.makeInputJSON(dictArgs); +} +// import PageResult from './PageResult'; +// onClick={goToPageHome} +// require + +function App() { + /* + const navigate = useNavigate(); + const goToPageHome = () => { + navigate.pushState('/PageHome'); + }; + */ + return ( +
+
+ logo +

+ Edit src/App.js and save to reload. +

+ + Learn React + + +
+ + }> + }> + +
+ {/* + + + + */} +
+
+
+ ); +} + + +export default App; \ No newline at end of file diff --git a/src/App.test.js b/src/App.test.jsx similarity index 100% rename from src/App.test.js rename to src/App.test.jsx diff --git a/src/Logo.png b/src/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d49d2284c9587269c404a66582d658e62614e944 GIT binary patch literal 14273 zcmd73WmuHa7cWXkhZ2K;5&}v$NS8`?4i4SjLw8C^DqYeYQZh71gGdU}-7SKMa`*WE z-*cXGp8MfG_cA8kKh$MQ8ZU73 z30zti{?gUL1a9NxNULSzV1dHJ#ls`a#VgD$NXz|Pn2%4GpO3D35IiZsEdNSM%ggX+ zX(1$2GzIgkeCM5rRVmMr2R=5cuw7Nmo?x96cHPy(mhjaX z;F9!zX&dN#pjf#q<_>&Nn zy7R4aP9GA3zv&qHs46jv*;mrGF`3kX{S! z%t<-!uxH2g%R^CaRnzqw4>aZ`+pN>!7+oySRzAbup1P>SKcJ~^;Q9`xJKf-$3j5tx zlwG14+$%$^NngMZ$O?F7Ix?0A9krN#$xodi-NQBZ2)@?ffgasF?%I=g=c9aLfU0!F z^igYEJ9jxWN~pC%#(fgf)rN@FaXO<=v@58-tGvTQ=}dZ6u@owbFE)Z=Xr>!SB0gR8 z;f3qZYLsVJJSMTgwsxsfd31t;q}~7O9iiwaGiR{9@qcZ!a+zKl7ni~^)Xf1zLpDw? zo%F+vS_+JLH>E4G(nKA}O<(qO9Tp0h3Xa|a=|62dI8 z2esmTZCDy$uHsYk+~RO+FrF~Ng|xPVLugwpAq;G_fa^UrITf%zm}jOya8TpleWQ|x zb4&PN#lggWp%{^jdTLEIOp*w+Jc-m7Nk^=>KvysYY~i2U@hpBvFM{>XU$!>VGfq6) z!wm}j0eP+Qb~ZJX0qlINeZi}q7kP?W2Bd6;TT=9B0eUpRY4mdf8!3y_4v_`_`akTE zNDbNNlei?WwKtkT13yWs@_gO1Ix?0@gJW=oFDYkFWmD@(IfsI88H&D&B}RAI9jMoI zfHBTC41W18TvaqAo3$r=67$_527nK>eb11+GgArIxh8aU{!IFT{p2j+-F+{^fnlT)agV|gjVp;VvPm3MQcujY0uqHuLqOL zPr}B@1r>{1LIi*;?k#*)qy22JN|al->==9TgDu#M+FwV2;R*7$Uz0O*S(Z(Vh{QT# z;;K@x`@74I)^d8wW@uC2C@Rb=3n~cj%dj%A@8Rb8F6<_hH8p3|p{4o>V^$?JfbHox zl6m9TD8|G7epGiY22#bO3Mec*7u)1GJX5z3NowFeFsb&Lz>-H&*82s&JZCU#Un10# zcb$1b!hi*+nzeH0o11i!#^d52+Uif;8v?Fncka2;booBiY)r9dLWc&W4M>~Hj?tif zF-EX)H^_YbZk$%KhBB5%(a?tLV}lS2<}30y+mDw^R~!lSTzMRqgvFe93_%}7Y#gcF>RDaEF9x2Rwnn^D8wBsuKgng$+*6H z61a()$^DfG$VKtFS)5$H7FY+Dp!~ZYKznvRHp;5nIv5P1`S;`&coKyfT$C@gp@0#3 zFzCy5IcrW!J}#hO@Z2m<_CLHmPJCta2Jn=|ppJAmloq_tz#wMuqriVw1C+mE&=UU# za45T>V`=nBOjTeU`CA4BU<{IOV0GUBal$#|>LzJ{d4Kp1Zw-C_M3DKvviBg9n+pYS zVDoPce1NF&gCwT6KpHTUe=}PEqOJdCZg`16Ly?n5pjn61AlB1aDZzsIhM@*PFv@^~ z{dx*?dhj1+&buASpa4XSa`P-|k`fT-`6mMdKs3YbA5kd~Oe7TmW#x|jXsha7U@u?E zjNJQpp$&k3Y5zY?WdWxVbN>XH0>?l}03ug=^Ka%G;0_vk{>{t|9NWJr%yRlqu%6(d zXa5nb3!o2{1vvEqGMl#gH?#l$J+n|?KozH;S@rHTjb0^+&}T+;_v=9q!Z8SvO=7Q) zBl(0U-?KH`q#ye6Vmq%Sp%~77+hl-E;O*hAe&p9E!qz56kCjEBeWKMar5k0K;@`ui zRfyBK*kA$MMITU3wfgx;?NZygc|bilK8+Ot)c!HzT}96p{7Q}Gl*3K>1aL}q*23~J z`a5!syV*dAugOTNQUdNic05bG*2fzIs{Gf==BQ-pk4$M2dCmiqy*M~V?Qmj6oE$zE z7hptI5GFRH{k$5iu^%XIy`Hd7UYW#@wrmoOv+;H`wLBDrmdvLxU->m(RI0@4AaBUr zM?fjTaqk@*Ly6^a)vS>PEqB*xA*->BMgIG@6<*uXiNGCJJcVv8>kj+hCZ@68JT*X_ znqPW0F%ql=#&PuJzyG%jnDhpyq^7=XV7+#e5H6w>oacl6kPR?PnMJe?aWBa^M|*O0 z(CcYsQDXE_pghHD=OR*%pg><_W>HetZz+x0Bo%J||-Hei;~Ud?ebL$BwN)RE9QkFBvS68*M5F29x?y zkKry-EcHx ze51~s0{E7!Q7O=PU(MFVu7s8hHrM4{yk?U&-P2qq)VLHdRv#B`@m4~JIi&-PO{F7I z3a+j^3nbzIJBdk@>uPTVNnsAkFwX$Y{%M)kaWHz@%`k;rT=&eZ-ES6>-}1G9^|Seo z^1)Fq5cYPJ%9n^1phNSYLV#3u4M&e7k1AM3aom6cdCzyCxq{I-qByLLO*PMObX^%h z_>o+pwk+mJH~zA@W+zn)CR*~!QO7-GAERKl*Y9QoRCF`dizOrMa^JFAf}M0@Ch@<= zmIi?Ek0&O4W#s-T_3wn#RbIjD?4v(&QuZMz+W!3$PT zxH(A2ey{TJH|;r;RFokwcdGEsF|+7&^;DEKMr$E!p8GGDSNc&!pKHEkKkQ4|3FUY&vslQN!SAD9v-4r^A>Ep! z8>M|I0cNFiN9>H8-Gi!K;LiB07Bux7e{xpMOg`$aNLBpWWStAgXec^6ijG6m`8LW6 z>?Wwme!(`>Lg8e5_{U@`@-!mZAQ^w30o^oB66uEs_Dbs`&{HCv@p$rsnp=?_Y*UqH(te z4n5%JHhsPwb_P~Vf@xi+*p*aQ%>%(75(t$fX)4lBd}dF>HRA*A8%Fc=;NXYo7eM82nh4z6CK)WVzjPgx zTj}ECj{~9>siv}>DUlCyiBp6q>|rXLJN!bS2K-YWJu$SJ97=n?6;)8=ui!+rOpaG% zI&*U|?BSN$Z%6p>Te2h4vaSzq5RdnwxdFGztqxvI2spi2d&6_}R1R|yub5yHv;&Au4>89vw>aO@=XW5dGd@lAYv-+iQn>3 zOXWSJbDFU(+6yOf{a`GnnxGz{;q*zNg*b<8%#j;lZD!r*Ji0TiVQsz zcy3|7>9BIfsyA0(OpUoFA!^-@lxlG~tR(f5%giysNWo(KWU+0b?8IGs_}}l8ES%4) z$tMG6?=YCQ_J87N5>=500WM2Epdn*HzPtp{I z{D)~0vYkS_>dDgp_|sa=qy>ZeL7-HNe9QU_08ww7(tC5Cka0sTBLX)TI24|bE`4BP zQ7|#nBWT-e{8)wm;w;xQ?uF2kiz=&HJb*r>s3#2!7g@RI@~R)nN#2i7`=#$ijGAl!bu2ctKEq;_nX-n8t@MJL|;!f3@t-qjhnmu#Fn0BCiL)Bo$|D{ zbD8SYXv>NevhFV1G(?YU%VMnA@@VRAleVZha>h?>=y~zIK!hBJPieXj(2)lVss`=VU0}`Sr#jeZ-?Mu4s7-Y{ypBPB3G&yYlQNt2eE5|ZwSU)ms@M*2H z$E|e!G|)*A7Ked|>3``yq7Y+bKN1a639{Ia?m2aB#U^B{o*rFv_>w)f zfXP;z9ciq$G$f$OHqn*=Mz-~BUlC<`&pE8ZNqDw z=_Mk>mYD3uS&yYS(L_z-dz&jFj82u&SUokjHN+N8Tm078QR3R??ilq#Y(uu!m?b?$ zYIV;mN=R{)c9!M!d~1ksT+-K(o140@H#e@|Z&#zHu%1|AU=o_5CIf|nJeIDwgf{Pz zy-W3-38#tPI^;%wPz#Q-AzwZ>hrMw*!aR!JtZ)=EzD`3UBS@;wYgh`QKBh5I759zL z`JBJWBS@fI5=vCdB##KW$r+%h3L!HmxEbm09e7x44US!AxK~eh-vvoOEM#R;AhN=T zK+lsB&?xLEbiM4+$S~xfYOnKD?QKx_4ki@>IQ)cBV-P?~^wv^56aw?pEY7fI?>>^E zSDfvJl5xocn5RFbbr0uWWq6P@NMpTAF0*yI|L9mCL4WBfqwxed8rc$u?y6)CnR&lM zQ=Q`3E-<0-FCQBzd^ib#zifF^D+%H%fv$5V9D~ZPo>eZG1m@^Nf93DZgf`wcLF*|o zIS84c2X0Dtt?MkgHe*Qlpyqj;43lvp0K<|B096DqwGh>MG&-}x!BJ&$D&bmQw=uPw zxHgVw_IQq?odOMTpO&vGFEG1sp15D3)s-*0hl_C0y84h}q1?|lvJ$DyoBf!;)l(~V z86N-|TD&T2uHZ*EkLqCKx~V){ykJ&wJ2+ zfBd}-qc5SKg#6glFbncCO<6zBIbF!W)s+p!F+w{8yZSNlFSTEp%|y%_&r?PdDy(-~ ztJ*q)y^S!7QTQuFNIsf_CI0Ie7gJD}I_{Z>A+uS~7Q!DYc}>73 z@6EM_81m~4#KSgpZbj0EC%$vE8GF1rqkegj%LP|Pgv3cd z%RKkc%L|yVVPUNb$EX*HxI*a(93CxXCD#vz(X9CB?WTtDyK@Q?=mI@h$zVU0{iE8o zud>8Hdl-U)-(@O;2swk4UZzsk2K7Ci0c?01!ETk1UX@>O5q*sFD`!ljQd36u?Q`^$ z#$jZ1aHg!qZ3wP-!g(5?TtNkOvJ;o3FMCuQr`wA>h{X1Y$#mH&{B|=GGj?cKSyI6) zBASHYuQzl&+?8xK!_I|v*}e|_ux2f1p)*nhaYP+gLWH>R&Ec70>$2}!mmgqO(r1hN zo6{L|tMxqXko-MQ)wSoHs!H|N@0WeB$y92=j7HaS8M`|2U}M@WVze5Hfa2Y^| zE=_Y?x9Ue^150@KVBWF^Rk3FH!^&$1mOJ*TIWOuW0JLOCIL<6!d&$qIdam~bm>N2J z(g8joC0_Zdg07QJC>*+MKT}jb;4GHCAI44R&iem zLf<_x=uXS1`hC^&)us#KIVXg%ZCm)sSY8br_RJd=s!kf)x75~_?~-fzrg;lg)V&-w zN!$!aTweeI9`MCfcJ2?`@J<&T!b$IsrqoR@62?=+u60zGFg-klAaWa>FD2d-h z9I7(eVMm5e!FZzCJ2ueOtV4rt!IYZ-*m|eF|DA(u)z&YR6#9W5RVyvb@VcY4(q}+#pV!{x9mfVR;*BwxSqqO%_?I_E?ns+3OU1wy}%(m zs9BHwj@ERcwyL1Y7&tv|IU*4HHMc0Tv$AG9Yxc+WOR;8=v@mqtxImwFr_Ora*IdX$|dNBB^A|_{)TpwhXeO#xh*J(DLLz(p-cwi;_;{SHhW5+;V7{VDsBj9`s;eftgKJ6%ZX6Y{-xJ zf(jBzAITWAATES#W*D1@7Q6?=(2qp*wKjLEjql;mzgTNrr1i+UjS*wJEv-wd5Ny``7o}qy8^5QT0G}J+dfq6G zyNhJ!P5C|Oc-Z{3B??bEKt!lzr!dJzPh{EGCZ#5E;bkke+|vER?HcWmGw2MY2I%UgHx~?VaCKv% z(OHdK5T_U%$s{>6dC1@j{|@ie_qkAS?tmvW^iZsO^2m(nazBKmk>ml8expe%-!R|Q zTM!*ZZxGq`U;-E9N~EkDu_7yI79EzG$8&~l3a@dViCI;qb#o>=3*VQN{wuL2sft$R z>77FV=;EeAuyw%xgX3q}Qp0lnxP^fQ4<9#G%U`^cgaAywDbjF?xzzKUA$-hWm=r1s z-%HXXKdt^Y2SC1Xt-jOkQ*?KL!3gicPQKCmeJ?cP5WAKgurKs^Wq6*72<_yv)E169 z%G$}9JGUyNnuIiPe2wzVT^ao1zc()-Y$<}la9-XVZP4?UsC*p9VMpTXM~Vdf5rD-8 zYXOhFyyzeODjEp9N~?k-4B|<=-$&%c%DSkO4(~7JOp9d${Ph-BV0(&Dpt#1!=Qf^j z&X^#o$j}i-)Z#^(Seb~({XJY5=^)nGxV_TgCoR-C!Z}xpsPr%oror?>j?l&W zcCoVGBKPksA7qeV-%Blb8_nblk1s%P$};|bVl{%jGP{B%Y;}T5NgT&4kTW~D=(aZ~ zJ8)Q<*6;vpX4%xXYVOE;>4&!*^lP-_NZ@%^KSNZ-K+Q~bQcQYQ*z^L6E&I14Z}uSM zfH29-z`qIo=8=k4L&D$pO^aD`DD{>m2*&*Fnsyq=w*lz)$LLW|GW`UvMl*AaR+%r0 z#+%7VPtUb|laX?xS9~+@n1w4zQG*IAPZPv*k}ujg1=@sbYdE@HAdr?8jHb+#r1csq zNTZQ;0SC{*L{nv$gjLA}Kxd^SC=TQ`z$W&eI&{I}$i(x0Vk*f2vWdSBzm5=DyF$FK?9&Ysasy#^Nl}&sLU(=uf9;>-U zusX<77B!O9s%#A^-OwOY(=c^b=joeh^A?@Q^>XWO4x%&aB|5_{L1>THnA;)5i;tuV`v7CiXsbxHfq zMSbhQyx0qKMLoh#zDn3JM$udRJopMALa3*|=y&oF55=w)XYw(xp?_jVL z*;EgCic(jedOdN32lwJ6{i{*$IMS|Bc}qZBSnaiop_)w~O^9z{dE@ zsbeCzCpAH*j^u3dc+7{rPv+R{xFqwrJW|DQ0_GTcXe8MGC|^cw!KlCVm!)kSq-MKr zFafuvvx%)6e4nEv#{N0CQ;g{Jy0_>sX>Cex|6`%Q3PTQ80WDGulHj}@Uf(lANE&e0 z8_?u;yH8{YZPqoCAPFpe166p@+I;9AO6Oz^(^gT)1fW(f&)bM)aZO+)23s~)0U~%z zWz{m-eA&zqeP>+GS`^LFJf4w0OLIjHBiX&;zJJ&opL-+vcLx19?&yH_%%y~(=p*x5 zIBET;>s-#akLdstu?s7ZuVFpUQiOTUZ7ir>!*DejGe5RI7e7(Iy9)F2x5UsP3)8~>DX<%GQ_^1@6{1~JA*`(o=3bNEJX zZI#gk(w5azvN1g&e1}jD9(aJuqFWnk&WWv62O4|xjv`3Z-mx#Aav7w$(U4Y19QrPiIseo%iteaCjGU;Ki>;IiV6 zbz^OpAi$v(>sqctxD&??8fS>FHVrUc<2E^{vq}~Vy@SyAW&W*dyi_#JzDToRqSa1M zj5jI!zd+rnK1}nd+I@ewzmcYD6)ajLWwOjiC((R+sa1t)>C<(Wmdh2W(&QGhUJp3A zeamF^b;XMlulUt?cvaWxu@SdyB-y7qg(u;O!3wE=eP*$5`=%HpSoTDtfyE=W*{Zqg z8eo%vNF8>)<1ZsOKB}t(!bT%#&5dJ^9+Gpl&9|C*4A~V~?Uz>`4If$STz6nOE*@jW z02$6#aW@sRZoe-q^9>~_A_HmZNeHjcWSmmYON1af|o$|g3tC2

Em!oM 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 E1;^LCwg3PC literal 0 HcmV?d00001 diff --git a/src/PageHome.jsx b/src/PageHome.jsx new file mode 100644 index 0000000..faa6272 --- /dev/null +++ b/src/PageHome.jsx @@ -0,0 +1,22 @@ +import React, { useState } from 'react'; +import objDefaults from './config'; // { defaultsMyBusiness, defaultsMyBusinessBank, defaultsTheirBusiness, defaultsTheirBusinessContact } +import MainContentForm from './components/MainContentForm'; + +const PageHome = () => { + const [formInvoiceData, setFormInvoiceData] = useState({ + ...objDefaults.getValuesDefaultFormMetadata, + ...objDefaults.getValuesDefaultMyBusiness, + ...objDefaults.getValuesDefaultMyBusinessBank, + ...objDefaults.getValuesDefaultTheirBusiness, + ...objDefaults.getValuesDefaultTheirBusinessContact, + ...objDefaults.getValuesDefaultInvoice + }); + console.log("formInvoiceData:", formInvoiceData); + return ( +

+ +
+ ) +}; + +export default PageHome; diff --git a/src/components/BlockFormSection.jsx b/src/components/BlockFormSection.jsx new file mode 100644 index 0000000..62dca12 --- /dev/null +++ b/src/components/BlockFormSection.jsx @@ -0,0 +1,25 @@ +import React from 'react'; +import InputWrapped from './Input'; + +const BlockFormSection = (props) => { + const { titleSection, inputs } = props.data; + + function report(titleSection, inputs) { + console.log("BlockFormSection"); + console.log("titleSection:", titleSection); + console.log("inputs:", inputs); + console.log(""); + } + report(titleSection, inputs); + + return ( +
+ + {inputs.map(input => ( + + ))} +
+ ); +}; + +export default BlockFormSection; \ No newline at end of file diff --git a/src/components/ContentFormInvoiceOrEstimate.jsx b/src/components/ContentFormInvoiceOrEstimate.jsx new file mode 100644 index 0000000..a9fe822 --- /dev/null +++ b/src/components/ContentFormInvoiceOrEstimate.jsx @@ -0,0 +1,176 @@ + +import React, { Component } from 'react'; +import BlockFormSection from './BlockFormSection'; +import methods from './MethodsInput'; +const makeInputJSON = (dictArgs) => { + return methods.makeInputJSON(dictArgs); +} + +class ContentFormInvoiceOrEstimate extends Component { + constructor(props) { + super(props); + this.state = this.props.stateMainContentForm; + this.initialiseElements(); + } + + handleChangeStateContentFormInvoiceOrEstimate(stateNew) { + const { stateMainContentForm, handleChangeStateMainContentForm } = this.props; + this.setState((statePrevious) => ({ + ...statePrevious, + ...stateNew + })); + handleChangeStateMainContentForm({ + ...stateMainContentForm, + ...stateNew + }); + } + + handleChangeInput(event) { + const { elementInput } = event.target; + this.handleChangeStateContentFormInvoiceOrEstimate({[elementInput.name]: elementInput.value}); + } + + initialiseElements() { + let typeForm = this.state.values['typeForm'] == "0" ? "Invoice" : "Estimate"; + let sectionsForm = [ + { + titleSection: typeForm, + inputs: [ + makeInputJSON({id: 'dateBilling' + typeForm, name: 'dateBilling' + typeForm, type: 'date', placeholder: this.state.placeholders['dateBilling' + typeForm], value: this.state.values['dateBilling' + typeForm], textLabel: 'Billing date:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'type' + typeForm, name: 'type' + typeForm, type: 'select', placeholder: this.state.placeholders['type' + typeForm], value: this.state.values['type' + typeForm], options: [ + {text: 'Goods', value:'0'}, + {text: 'Services', value:'1'} + ], textLabel: 'Invoice type:', onChange: this.handleChangeInput}) + ] + } + ]; + let sectionsGoods = []; + if (this.state.values['type' + typeForm] == '0') { + sectionsForm = sectionsForm.concat([ + { + titleSection: 'Goods', + inputs: [ + makeInputJSON({id: 'quantityGoods' + typeForm, name: 'quantityGoods' + typeForm, type: 'number', placeholder: this.state.placeholders['quantityGoods' + typeForm], value: this.state.values['quantityGoods' + typeForm], textLabel: 'Number of different goods:', onChange: this.handleChangeInput}) + ] + } + ]); + if (this.state.values['quantityGoods' + typeForm] > 0) { + for (let i = 0; i < this.state.values['quantityGoods' + typeForm]; i++) { + sectionsGoods = sectionsGoods.concat([ + { + titleSection: 'Good ' + (i + 1), + inputs: [ + makeInputJSON({id: 'nameGood' + typeForm + (i + 1), name: 'nameGood' + typeForm + (i + 1), type: 'text', placeholder: this.state.placeholders['nameGood' + typeForm + (i + 1)], value: this.state.values['nameGood' + typeForm + (i + 1)], textLabel: 'Name:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'valueGood' + typeForm + (i + 1), name: 'valueGood' + typeForm + (i + 1), type: 'number', placeholder: this.state.placeholders['valueGood' + typeForm + (i + 1)], value: this.state.values['valueGood' + typeForm + (i + 1)], textLabel: 'Value:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'quantityGood' + typeForm + (i + 1), name: 'quantityGood' + typeForm + (i + 1), type: 'number', placeholder: this.state.placeholders['quantityGood' + typeForm + (i + 1)], value: this.state.values['quantityGood' + typeForm + (i + 1)], textLabel: 'Quantity:', onChange: this.handleChangeInput}) + ] + } + ]); + } + } + } + let sectionsServices = []; + let subsectionsServices = []; + console.log("this.state.values[" + "type" + typeForm + "]:", this.state.values['type' + typeForm]); + if (this.state.values['type' + typeForm] == '1') { + sectionsForm = sectionsForm.concat([ + { + titleSection: 'Services', + inputs: [ + makeInputJSON({id: 'quantityServices' + typeForm, name: 'quantityServices' + typeForm, type: 'number', placeholder: this.state.placeholders['quantityServices' + typeForm], value: this.state.values['quantityServices' + typeForm], textLabel: 'Number of different services:', onChange: this.handleChangeInput}) + ] + } + ]); + console.log("this.state.values[" + 'quantityServices' + typeForm + "]:", this.state.values['quantityServices' + typeForm]); + if (this.state.values['quantityServices' + typeForm] > 0) { + let j; + for (let i = 0; i < this.state.values['quantityServices' + typeForm]; i++) { + console.log("adding service " + (i + 1)); + sectionsServices = sectionsServices.concat([ + { + titleSection: 'Service ' + (i + 1), + inputs: [ + makeInputJSON({id: 'discretisationRateService' + typeForm + (i + 1), name: 'discretisationRateService' + typeForm + (i + 1), type: 'select', placeholder: this.state.placeholders['discretisationRateService' + typeForm + (i + 1)], value: this.state.values['discretisationRateService' + typeForm + (i + 1)], options: [ + {text: 'Minute', value:'m'}, + {text: 'Hour', value:'h'}, + {text: 'Day', value:'d'}, + {text: 'Week', value:'w'} + ], textLabel: 'Rate discretisation:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'quantityDiscretisationRateService' + typeForm + (i + 1), name: 'quantityDiscretisationRateService' + typeForm + (i + 1), type: 'number', placeholder: this.state.placeholders['quantityDiscretisationRateService' + typeForm + (i + 1)], value: this.state.values['quantityDiscretisationRateService' + typeForm + (i + 1)], textLabel: 'Quantity of rate discretisations per minimum unit rate:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'rateService' + typeForm + (i + 1), name: 'rateService' + typeForm + (i + 1), type: 'number', placeholder: this.state.placeholders['rateService' + typeForm + (i + 1)], value: this.state.values['rateService' + typeForm + (i + 1)], textLabel: 'Rate [£ / hour]:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'discretisationDurationService' + typeForm + (i + 1), name: 'discretisationDurationService' + typeForm + (i + 1), type: 'select', placeholder: this.state.placeholders['discretisationDurationService' + typeForm + (i + 1)], value: this.state.values['discretisationDurationService' + typeForm + (i + 1)], options: [ + {text: 'Day', value:'d'}, + {text: 'Week', value:'w'}, + {text: 'Month', value:'M'}, + {text: 'Year', value:'y'} + ], textLabel: 'Duration discretisation:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'quantityDiscretisationDurationService' + typeForm + (i + 1), name: 'quantityDiscretisationDurationService' + typeForm + (i + 1), type: 'number', placeholder: this.state.placeholders['quantityDiscretisationDurationService' + typeForm + (i + 1)], value: this.state.values['quantityDiscretisationDurationService' + typeForm + (i + 1)], textLabel: 'Quantity of duration discretisations per billing period:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'quantityBillingPeriodService' + typeForm + (i + 1), name: 'quantityBillingPeriodService' + typeForm + (i + 1), type: 'number', placeholder: this.state.placeholders['quantityBillingPeriodService' + typeForm + (i + 1)], value: this.state.values['quantityBillingPeriodService' + typeForm + (i + 1)], textLabel: 'Quantity of billing periods:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'isIncrementalBillingPeriodIdsService' + typeForm + (i + 1), name: 'isIncrementalBillingPeriodIdsService' + typeForm + (i + 1), type: 'checkbox', placeholder: this.state.placeholders['isIncrementalBillingPeriodIdsService' + typeForm + (i + 1)], value: this.state.values['isIncrementalBillingPeriodIdsService' + typeForm + (i + 1)], textLabel: 'Are billing period IDs incremental?', onChange: this.handleChangeInput}), + makeInputJSON({id: 'descriptionIncrementalService' + typeForm + (i + 1), name: 'descriptionIncrementalService' + typeForm + (i + 1), type: 'text', placeholder: this.state.placeholders['descriptionIncrementalService' + typeForm + (i + 1)], value: this.state.values['descriptionIncrementalService' + typeForm + (i + 1)], textLabel: 'Description:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'idBillingPeriodFirstIncrementalService' + typeForm + (i + 1), name: 'idBillingPeriodFirstIncrementalService' + typeForm + (i + 1), type: 'number', placeholder: this.state.placeholders['idBillingPeriodFirstIncrementalService' + typeForm + (i + 1)], value: this.state.values['idBillingPeriodFirstIncrementalService' + typeForm + (i + 1)], textLabel: 'First billing period ID:', onChange: this.handleChangeInput}) + ] + } + ]); + let subsections = []; + if (this.state.values['quantityBillingPeriodService' + typeForm + (i + 1)] > 0) { + for (j = 0; j < this.state.values['quantityBillingPeriodService' + typeForm + (i + 1)]; j++) { + subsections = subsections.concat([ + { + titleSection: 'Service billing period ' + (j + 1), + inputs: [ + makeInputJSON({id: 'descriptionIncrementService' + typeForm + (i + 1) + 's' + (j + 1), name: 'descriptionIncrementService' + typeForm + (i + 1) + 's' + (j + 1), type: 'text', placeholder: this.state.placeholders['descriptionIncrementService' + typeForm + (i + 1) + 's' + (j + 1)], value: this.state.values['descriptionIncrementService' + typeForm + (i + 1) + 's' + (j + 1)], textLabel: 'Description:', onChange: this.handleChangeInput}), + makeInputJSON({id: 'quantityRatePeriodsIncrementService' + typeForm + (i + 1) + 's' + (j + 1), name: 'quantityRatePeriodsIncrementService' + typeForm + (i + 1) + 's' + (j + 1), type: 'number', placeholder: this.state.placeholders['quantityRatePeriodsIncrementService' + typeForm + (i + 1) + 's' + (j + 1)], value: this.state.values['quantityRatePeriodsIncrementService' + typeForm + (i + 1) + 's' + (j + 1)], textLabel: 'Quantity of unit rate periods worked:', onChange: this.handleChangeInput}) + ] + } + ]); + } + } + subsectionsServices = subsectionsServices.concat(subsections); + } + } + } + console.log("this.state.values['typeForm']:", this.state.values['typeForm']); + console.log("typeForm:", typeForm); + console.log("values:", this.state.values); + console.log("sectionsGoods:", sectionsGoods); + console.log("sectionsServices:", sectionsServices); + console.log("subsectionsServices:", subsectionsServices); + const dataInvoiceOrEstimate = { + // ...stateContentFormInvoiceOrEstimate, + sectionsForm: sectionsForm, + sectionsGoods: sectionsGoods, + sectionsServices: sectionsServices, + subsectionsServices: subsectionsServices, + }; + this.handleChangeStateContentFormInvoiceOrEstimate(dataInvoiceOrEstimate); + } + + render() { + let typeForm = this.state.values['typeForm'] == "0" ? "Invoice" : "Estimate"; + return ( +
+ {this.state.sectionsForm.map(section => ( + + ))} + {(this.state.sectionsGoods.length > 0) && ( + this.state.sectionsGoods.map(section => ( + + )) + )} + {(this.state.sectionsServices.length > 0) && ( + this.state.sectionsServices.map(section => ( + + )) + )} + {(this.state.subsectionsServices.length > 0) && ( + this.state.subsectionsServices.map(section => ( + + )) + )} +
+ ); + } +} + +export default ContentFormInvoiceOrEstimate; \ No newline at end of file diff --git a/src/components/ControlsFillDefaults.jsx b/src/components/ControlsFillDefaults.jsx new file mode 100644 index 0000000..873239d --- /dev/null +++ b/src/components/ControlsFillDefaults.jsx @@ -0,0 +1,113 @@ +import React from 'react'; + +function date2str(date_in) { + return date_in.getFullYear().toString() + '-' + (date_in.getMonth() + 1).toString().padStart(2, '0') + '-' + date_in.getDate().toString().padStart(2, '0'); +} +function getDateBilling() { + return date2str(new Date(Date.now.getFullYear(), Date.now.getMonth(), -1)); +} +function getValuesDefault() { + return { + typeForm: '0', + currency: '0', + nameMyBusiness: 'Precision And Research Technology Systems Limited', + companyNumberMyBusiness: '13587499', + emailMyBusiness: 'edward.middletonsmith@gmail.com', + address1MyBusiness: 'Unit 12a', + address2MyBusiness: 'Somers Road', + address3MyBusiness: 'Rugby', + address4MyBusiness: 'Warwickshire', + address5MyBusiness: 'CV22 7DH', + bankNameMyBusiness: 'Starling', + accountNameMyBusiness: 'Precision And Research Technology Systems Limited', + accountNumberMyBusiness: '40168366', + sortCodeMyBusiness: '60-83-71', + nameTheirBusiness: 'Contechs Technical Resourcing Limited', + codeTheirBusiness: 'Contechs', + emailTheirBusiness: 'account@contechs.co.uk', + phoneTheirBusiness: '01268 582900', + address1TheirBusiness: '2 Sable Court', + address2TheirBusiness: 'Southfields Business Park', + address3TheirBusiness: 'Basildon', + address4TheirBusiness: 'Essex', + address5TheirBusiness: 'SS15 6SR', + nameContactTheirBusiness: 'Simon Bant', + address1ContactTheirBusiness: 'Jaguar Land Rover', + address2ContactTheirBusiness: 'Banbury Road', + address3ContactTheirBusiness: 'Gaydon', + address4ContactTheirBusiness: 'Warwickshire', + address5ContactTheirBusiness: 'CV35 0RR', + dateBillingInvoice: getDateBilling(), + typeInvoice: '1', // services + quantityServicesInvoice: 1, + + discretisationRateServiceInvoice1: 'h', + quantityDiscretisationRateServiceInvoice1: 1, + rateServiceInvoice1: 23.94, + discretisationDurationServiceInvoice1: 'w', + quantityDiscretisationDurationServiceInvoice1: 1, + quantityBillingPeriodServiceInvoice1: 4, + isIncrementalBillingPeriodIdsServiceInvoice1: true, + descriptionIncrementalServiceInvoice1: "Contractor services - week ", + idBillingPeriodFirstIncrementalServiceInvoice1: 1, + + descriptionIncrementServiceInvoice1s1: "Contractor services - week 1", + quantityRatePeriodsIncrementServiceInvoice1s1: 40, + descriptionIncrementServiceInvoice1s2: "Contractor services - week 2", + quantityRatePeriodsIncrementServiceInvoice1s2: 40, + descriptionIncrementServiceInvoice1s3: "Contractor services - week 3", + quantityRatePeriodsIncrementServiceInvoice1s3: 40, + descriptionIncrementServiceInvoice1s4: "Contractor services - week 4", + quantityRatePeriodsIncrementServiceInvoice1s4: 40, + }; +} + +const ControlsFillDefaults = () => { + const defaults = getValuesDefault(); + + function getDefaultsMyBusiness() { + localStorage.setItem('nameMyBusiness', 'Precision And Research Technology Systems Limited'); + localStorage.setItem('companyNumberMyBusiness', '13587499'); + localStorage.setItem('emailMyBusiness', 'edward.middletonsmith@gmail.com'); + localStorage.setItem('address1', 'Unit 12a'); + localStorage.setItem('address2', 'Somers Road'); + localStorage.setItem('address3', 'Rugby'); + localStorage.setItem('address4', 'Warwickshire'); + localStorage.setItem('address5', 'CV22 7DH'); + } + function getDefaultsMyBusinessBank() { + localStorage.setItem('bankName', 'Starling'); + localStorage.setItem('accountName', 'Precision And Research Technology Systems Limited'); + localStorage.setItem('accountNumber', '40168366'); + localStorage.setItem('sortCode', '60-83-71'); + } + function getDefaultsTheirBusiness() { + localStorage.setItem('name', 'Contechs Technical Resourcing Limited'); + localStorage.setItem('code', 'Contechs'); + localStorage.setItem('email', 'account@contechs.co.uk'); + localStorage.setItem('phone', '01268 582900'); + localStorage.setItem('address1', '2 Sable Court'); + localStorage.setItem('address2', 'Southfields Business Park'); + localStorage.setItem('address3', 'Basildon'); + localStorage.setItem('address4', 'Essex'); + localStorage.setItem('address5', 'SS15 6SR'); + } + function getDefaultsTheirBusinessContact() { + localStorage.setItem('name', 'Simon Bant'); + localStorage.setItem('address1', 'Jaguar Land Rover'); + localStorage.setItem('address2', 'Banbury Road'); + localStorage.setItem('address3', 'Gaydon'); + localStorage.setItem('address4', 'Warwickshire'); + localStorage.setItem('address5', 'CV35 0RR'); + } + + return ( +
+ + + +
+ ) +}; + +export default ControlsFillDefaults; \ No newline at end of file diff --git a/src/components/Input.jsx b/src/components/Input.jsx new file mode 100644 index 0000000..86ff22b --- /dev/null +++ b/src/components/Input.jsx @@ -0,0 +1,51 @@ +import React from 'react'; + +const makeInputJSON = (dictArgs) => { + const {id, name, value = null, textLabel = null, type = null, placeholder = null, stepValue = null, minValue = null, options = null, onChange = function() {}} = dictArgs; + return { + id: id, + name: name, + value: value, + textLabel: textLabel, + type: type, + placeholder: placeholder, + stepValue: stepValue, + minValue: minValue, + options: options, + onChange: onChange + }; +}; + +const InputWrapped = (props) => { + const { id, name, value, textLabel, type, placeholder, step, valueMin, options, onChange } = props.data; + + return ( +
+ + {(type == 'date') && ( + + )} + {(type == 'text') && ( + + )} + {(type == 'number') && ( + + )} + {(type == 'checkbox') && ( + + )} + {(type == 'select') && ( + + )} + {(type == 'button') && ( + + )} +
+ ) +}; + +export default InputWrapped; // { InputWrapped, makeInputJSON }; \ No newline at end of file diff --git a/src/components/MainContentForm.jsx b/src/components/MainContentForm.jsx new file mode 100644 index 0000000..a0a8252 --- /dev/null +++ b/src/components/MainContentForm.jsx @@ -0,0 +1,175 @@ +import React, { Component } from 'react'; +import BlockFormSection from './BlockFormSection'; +// import getValuesDefault from './ControlsFillDefaults'; +import InputWrapped from './Input'; +import ContentFormInvoiceOrEstimate from './ContentFormInvoiceOrEstimate'; +import methods from './MethodsInput'; +const makeInputJSON = (dictArgs) => { + return methods.makeInputJSON(dictArgs); +} + +class MainContentForm extends Component { + + constructor(props) { + super(props); + const values = { + typeForm: "0", + currency: '0', + nameMyBusiness: '', + companyNumberMyBusiness: '', + emailMyBusiness: '', + address1MyBusiness: '', + address2MyBusiness: '', + address3MyBusiness: '', + address4MyBusiness: '', + address5MyBusiness: '', + bankNameMyBusiness: '', + accountNameMyBusiness: '', + accountNumberMyBusiness: '', + sortCodeMyBusiness: '', + nameTheirBusiness: '', + codeTheirBusiness: '', + emailTheirBusiness: '', + phoneTheirBusiness: '', + address1TheirBusiness: '', + address2TheirBusiness: '', + address3TheirBusiness: '', + address4TheirBusiness: '', + address5TheirBusiness: '', + nameContactTheirBusiness: '', + address1ContactTheirBusiness: '', + address2ContactTheirBusiness: '', + address3ContactTheirBusiness: '', + address4ContactTheirBusiness: '', + address5ContactTheirBusiness: '', + typeInvoice: '', + quantityServicesInvoice: '', + discretisationRateServiceInvoice1: '', + quantityDiscretisationRateServiceInvoice1: '', + rateServiceInvoice1: '', + discretisationDurationServiceInvoice1: '', + quantityDiscretisationDurationServiceInvoice1: '', + quantityBillingPeriodServiceInvoice1: '', + isIncrementalBillingPeriodIdsServiceInvoice1: '', + descriptionIncrementalServiceInvoice1: '', + idBillingPeriodFirstIncrementalServiceInvoice1: '', + descriptionIncrementServiceInvoice1s1: '', + quantityRatePeriodsIncrementServiceInvoice1s1: '', + descriptionIncrementServiceInvoice1s2: '', + quantityRatePeriodsIncrementServiceInvoice1s2: '', + descriptionIncrementServiceInvoice1s3: '', + quantityRatePeriodsIncrementServiceInvoice1s3: '', + descriptionIncrementServiceInvoice1s4: '', + quantityRatePeriodsIncrementServiceInvoice1s4: '' + }; + this.state = { values: {...values, ...props.values }, placeholders: props.placeholders, sectionsMainContentForm: [], sectionsForm: [], sectionsGoods: [], sectionsServices: [], subsectionsServices: []}; + console.log("placeholders: ", props.placeholders); + this.initialiseElements(); + } + + handleChangeStateMainContentForm(stateNew) { + this.setState((statePrevious) => ({ + ...statePrevious, + ...stateNew + })); + } + + handleChangeInput(event) { + const { elementInput } = event.target; + this.handleChangeStateMainContentForm({[elementInput.name]: elementInput.value}); + } + + initialiseElements() { + let sectionsMainContentForm = [ + { + titleSection: 'Invoice Metadata', + inputs: [ + makeInputJSON({id: 'typeForm', name: 'typeForm', value: this.state.values['typeForm'], textLabel: 'Form type:', type: 'select', placeholder: this.state.placeholders['typeForm'], options: [ + {text: '-', value: '0'}, + {text: 'INVOICE', value: '1'}, + {text: 'ESTIMATE', value: '2'}, + {text: 'PAYMENT-PLAN', value: '3'} + ], onChange: this.handleChangeInput}), + makeInputJSON({id: 'currency', name: 'currency', value: this.state.values['currency'], textLabel: 'Currency:', type: 'select', options: [ + {text: '£', value: '0'}, + {text: '$', value: '1'}, + {text: '€', value: '2'}, + {text: 'Other', value: '3'} + ], onChange: this.handleChangeInput}) + ] + }, + { + titleSection: 'My Business Details', + inputs: [ + makeInputJSON({id: 'nameMyBusiness', name: 'nameMyBusiness', value: this.state.values['nameMyBusiness'], textLabel: 'Name:', type: 'text', placeholder: this.state.placeholders['nameMyBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'companyNumberMyBusiness', name: 'companyNumberMyBusiness', value: this.state.values['companyNumberMyBusiness'], textLabel: 'Company number:', type: 'text', placeholder: this.state.placeholders['companyNumberMyBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'emailMyBusiness', name: 'emailMyBusiness', value: this.state.values['emailMyBusiness'], textLabel: 'Email:', type:'text', placeholder: this.state.placeholders['emailMyBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address1MyBusiness', name: 'address1MyBusiness', value: this.state.values['address1MyBusiness'], textLabel: 'Address line 1:', type:'text', placeholder: this.state.placeholders['address1MyBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address2MyBusiness', name: 'address2MyBusiness', value: this.state.values['address2MyBusiness'], textLabel: 'Address line 2:', type:'text', placeholder: this.state.placeholders['address2MyBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address3MyBusiness', name: 'address3MyBusiness', value: this.state.values['address3MyBusiness'], textLabel: 'Address line 3:', type:'text', placeholder: this.state.placeholders['address3MyBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address4MyBusiness', name: 'address4MyBusiness', value: this.state.values['address4MyBusiness'], textLabel: 'Address line 4:', type:'text', placeholder: this.state.placeholders['address4MyBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address5MyBusiness', name: 'address5MyBusiness', value: this.state.values['address5MyBusiness'], textLabel: 'Address line 5:', type:'text', placeholder: this.state.placeholders['address5MyBusiness'], onChange: this.handleChangeInput}) + ] + }, + { + titleSection: 'My Business Bank Details', + inputs: [ + makeInputJSON({id: 'nameBankMyBusiness', name: 'nameBankMyBusiness', value: this.state.values['nameBankMyBusiness'], textLabel: 'Bank name:', type:'text', placeholder: this.state.placeholders['nameBankMyBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'accountNameBankMyBusiness', name: 'accountNameBankMyBusiness', value: this.state.values['accountNameBankMyBusiness'], textLabel: 'Account name:', type:'text', placeholder: this.state.placeholders['accountNameBankMyBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'accountNumberBankMyBusiness', name: 'accountNumberBankMyBusiness', value: this.state.values['accountNumberBankMyBusiness'], textLabel: 'Account number:', type:'text', placeholder: this.state.placeholders['accountNumberBankMyBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'sortCodeBankMyBusiness', name: 'sortCodeBankMyBusiness', value: this.state.values['sortCodeBankMyBusiness'], textLabel: 'Sort code:', type:'text', placeholder: this.state.placeholders['sortCodeBankMyBusiness'], onChange: this.handleChangeInput}) + ] + }, + { + titleSection: 'Their Business Details', + inputs: [ + makeInputJSON({id: 'nameTheirBusiness', name: 'nameTheirBusiness', value: this.state.values['nameTheirBusiness'], textLabel: 'Name:', type:'text', placeholder: this.state.placeholders['nameTheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'codeTheirBusiness', name: 'codeTheirBusiness', value: this.state.values['codeTheirBusiness'], textLabel: 'Code:', type:'text', placeholder: this.state.placeholders['codeTheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'emailTheirBusiness', name: 'emailTheirBusiness', value: this.state.values['emailTheirBusiness'], textLabel: 'Email:', type:'text', placeholder: this.state.placeholders['emailTheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'phoneTheirBusiness', name: 'phoneTheirBusiness', value: this.state.values['phoneTheirBusiness'], textLabel: 'Phone:', type:'text', placeholder: this.state.placeholders['phoneTheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address1TheirBusiness', name: 'address1TheirBusiness', value: this.state.values['address1TheirBusiness'], textLabel: 'Address line 1:', type:'text', placeholder: this.state.placeholders['address1TheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address2TheirBusiness', name: 'address2TheirBusiness', value: this.state.values['address2TheirBusiness'], textLabel: 'Address line 2:', type:'text', placeholder: this.state.placeholders['address2TheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address3TheirBusiness', name: 'address3TheirBusiness', value: this.state.values['address3TheirBusiness'], textLabel: 'Address line 3:', type:'text', placeholder: this.state.placeholders['address3TheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address4TheirBusiness', name: 'address4TheirBusiness', value: this.state.values['address4TheirBusiness'], textLabel: 'Address line 4:', type:'text', placeholder: this.state.placeholders['address4TheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address5TheirBusiness', name: 'address5TheirBusiness', value: this.state.values['address5TheirBusiness'], textLabel: 'Address line 5:', type:'text', placeholder: this.state.placeholders['address5TheirBusiness'], onChange: this.handleChangeInput}) + ] + }, + { + titleSection: 'Their Business Contact Details', + inputs: [ + makeInputJSON({id: 'nameContactTheirBusiness', name: 'nameContactTheirBusiness', value: this.state.values['nameContactTheirBusiness'], textLabel: 'Name:', type:'text', placeholder: this.state.placeholders['nameContactTheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address1ContactTheirBusiness', name: 'address1ContactTheirBusiness', value: this.state.values['address1ContactTheirBusiness'], textLabel: 'Address line 1:', type:'text', placeholder: this.state.placeholders['address1ContactTheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address2ContactTheirBusiness', name: 'address2ContactTheirBusiness', value: this.state.values['address2ContactTheirBusiness'], textLabel: 'Address line 2:', type:'text', placeholder: this.state.placeholders['address2ContactTheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address3ContactTheirBusiness', name: 'address3ContactTheirBusiness', value: this.state.values['address3ContactTheirBusiness'], textLabel: 'Address line 3:', type:'text', placeholder: this.state.placeholders['address3ContactTheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address4ContactTheirBusiness', name: 'address4ContactTheirBusiness', value: this.state.values['address4ContactTheirBusiness'], textLabel: 'Address line 4:', type:'text', placeholder: this.state.placeholders['address4ContactTheirBusiness'], onChange: this.handleChangeInput}), + makeInputJSON({id: 'address5ContactTheirBusiness', name: 'address5ContactTheirBusiness', value: this.state.values['address5ContactTheirBusiness'], textLabel: 'Address line 5:', type:'text', placeholder: this.state.placeholders['address5ContactTheirBusiness'], onChange: this.handleChangeInput}) + ] + } + ]; + this.handleChangeStateMainContentForm({ sectionsMainContentForm: sectionsMainContentForm }); + } + handleSubmit() { }; + clearForm() { }; + + render() { + let typeForm = this.state.values['typeForm'] == "0" ? "Invoice" : "Estimate"; + return ( +
+ {this.state.sectionsMainContentForm.map(section => ( + + ))} + {/* */} + {typeForm} + {(typeForm == 'Invoice' || typeForm == 'Estimate') && + + } +
+ + +
+ + ); + } +} + +export default MainContentForm; \ No newline at end of file diff --git a/src/components/MainContentForm_functional.jsx b/src/components/MainContentForm_functional.jsx new file mode 100644 index 0000000..290357b --- /dev/null +++ b/src/components/MainContentForm_functional.jsx @@ -0,0 +1,322 @@ +import React, {useEffect, useState} from 'react'; +import BlockFormSection from './BlockFormSection'; +import getValuesDefault from './ControlsFillDefaults'; +import InputWrapped from './Input'; +import ContentFormInvoiceOrEstimate from './ContentFormInvoiceOrEstimate'; +import methods from './MethodsInput'; +const makeInputJSON = (dictArgs) => { + return methods.makeInputJSON(dictArgs); +} + +const getValuesDefaultFromPlaceholders = (placeholdersDefault) => { + const values = { + typeForm: "0", + currency: '0', + nameMyBusiness: '', + companyNumberMyBusiness: '', + emailMyBusiness: '', + address1MyBusiness: '', + address2MyBusiness: '', + address3MyBusiness: '', + address4MyBusiness: '', + address5MyBusiness: '', + bankNameMyBusiness: '', + accountNameMyBusiness: '', + accountNumberMyBusiness: '', + sortCodeMyBusiness: '', + nameTheirBusiness: '', + codeTheirBusiness: '', + emailTheirBusiness: '', + phoneTheirBusiness: '', + address1TheirBusiness: '', + address2TheirBusiness: '', + address3TheirBusiness: '', + address4TheirBusiness: '', + address5TheirBusiness: '', + nameContactTheirBusiness: '', + address1ContactTheirBusiness: '', + address2ContactTheirBusiness: '', + address3ContactTheirBusiness: '', + address4ContactTheirBusiness: '', + address5ContactTheirBusiness: '', + typeInvoice: '', + quantityServicesInvoice: '', + discretisationRateServiceInvoice1: '', + quantityDiscretisationRateServiceInvoice1: '', + rateServiceInvoice1: '', + discretisationDurationServiceInvoice1: '', + quantityDiscretisationDurationServiceInvoice1: '', + quantityBillingPeriodServiceInvoice1: '', + isIncrementalBillingPeriodIdsServiceInvoice1: '', + descriptionIncrementalServiceInvoice1: '', + idBillingPeriodFirstIncrementalServiceInvoice1: '', + descriptionIncrementServiceInvoice1s1: '', + quantityRatePeriodsIncrementServiceInvoice1s1: '', + descriptionIncrementServiceInvoice1s2: '', + quantityRatePeriodsIncrementServiceInvoice1s2: '', + descriptionIncrementServiceInvoice1s3: '', + quantityRatePeriodsIncrementServiceInvoice1s3: '', + descriptionIncrementServiceInvoice1s4: '', + quantityRatePeriodsIncrementServiceInvoice1s4: '' + }; // = placeholdersDefault; + /* + const combined = {}; + for (const key in values) { + if (placeholdersDefault.hasOwnProperty(key)) { + combined[key] = placeholdersDefault[key]; + } + else { + combined[key] = values[key]; + } + } + return combined; + */ + return Object.keys(values).reduce((result, key) => { + if (placeholdersDefault.hasOwnProperty(key)) { + result[key] = placeholdersDefault[key]; + } else { + result[key] = values[key]; + } + return result; + }, {}); + /*{ + typeForm: typeForm, + currency: currency, + nameMyBusiness: nameMyBusiness, + companyNumberMyBusiness: companyNumberMyBusiness, + emailMyBusiness: emailMyBusiness, + address1MyBusiness: address1MyBusiness, + address2MyBusiness: address2MyBusiness, + address3MyBusiness: address3MyBusiness, + address4MyBusiness: address4MyBusiness, + address5MyBusiness: address5MyBusiness, + bankNameMyBusiness: bankNameMyBusiness, + accountNameMyBusiness: accountNameMyBusiness, + accountNumberMyBusiness: accountNumberMyBusiness, + sortCodeMyBusiness: sortCodeMyBusiness, + nameTheirBusiness: nameTheirBusiness, + codeTheirBusiness: codeTheirBusiness, + emailTheirBusiness: emailTheirBusiness, + phoneTheirBusiness: phoneTheirBusiness, + address1TheirBusiness: address1TheirBusiness, + address2TheirBusiness: address2TheirBusiness, + address3TheirBusiness: address3TheirBusiness, + address4TheirBusiness: address4TheirBusiness, + address5TheirBusiness: address5TheirBusiness, + nameContactTheirBusiness: nameContactTheirBusiness, + address1ContactTheirBusiness: address1ContactTheirBusiness, + address2ContactTheirBusiness: address2ContactTheirBusiness, + address3ContactTheirBusiness: address3ContactTheirBusiness, + address4ContactTheirBusiness: address4ContactTheirBusiness, + address5ContactTheirBusiness: address5ContactTheirBusiness, + typeInvoice: typeInvoice, + quantityServicesInvoice: quantityServicesInvoice, + discretisationRateServiceInvoice1: discretisationRateServiceInvoice1, + quantityDiscretisationRateServiceInvoice1: quantityDiscretisationRateServiceInvoice1, + rateServiceInvoice1: rateServiceInvoice1, + discretisationDurationServiceInvoice1: discretisationDurationServiceInvoice1, + quantityDiscretisationDurationServiceInvoice1: quantityDiscretisationDurationServiceInvoice1, + quantityBillingPeriodServiceInvoice1: quantityBillingPeriodServiceInvoice1, + isIncrementalBillingPeriodIdsServiceInvoice1: isIncrementalBillingPeriodIdsServiceInvoice1, + descriptionIncrementalServiceInvoice1: descriptionIncrementalServiceInvoice1, + idBillingPeriodFirstIncrementalServiceInvoice1: idBillingPeriodFirstIncrementalServiceInvoice1, + descriptionIncrementServiceInvoice1s1: descriptionIncrementServiceInvoice1s1, + quantityRatePeriodsIncrementServiceInvoice1s1: quantityRatePeriodsIncrementServiceInvoice1s1, + descriptionIncrementServiceInvoice1s2: descriptionIncrementServiceInvoice1s2, + quantityRatePeriodsIncrementServiceInvoice1s2: quantityRatePeriodsIncrementServiceInvoice1s2, + descriptionIncrementServiceInvoice1s3: descriptionIncrementServiceInvoice1s3, + quantityRatePeriodsIncrementServiceInvoice1s3: quantityRatePeriodsIncrementServiceInvoice1s3, + descriptionIncrementServiceInvoice1s4: descriptionIncrementServiceInvoice1s4, + quantityRatePeriodsIncrementServiceInvoice1s4: quantityRatePeriodsIncrementServiceInvoice1s4 + };*/ +} + +const MainContentForm = (props) => { + const placeholdersDefault = props.data; + // const valuesDefault = getValuesDefault(); + console.log("placeholders: ", placeholdersDefault); + const values = { + typeForm: "0", + currency: '0', + nameMyBusiness: '', + companyNumberMyBusiness: '', + emailMyBusiness: '', + address1MyBusiness: '', + address2MyBusiness: '', + address3MyBusiness: '', + address4MyBusiness: '', + address5MyBusiness: '', + bankNameMyBusiness: '', + accountNameMyBusiness: '', + accountNumberMyBusiness: '', + sortCodeMyBusiness: '', + nameTheirBusiness: '', + codeTheirBusiness: '', + emailTheirBusiness: '', + phoneTheirBusiness: '', + address1TheirBusiness: '', + address2TheirBusiness: '', + address3TheirBusiness: '', + address4TheirBusiness: '', + address5TheirBusiness: '', + nameContactTheirBusiness: '', + address1ContactTheirBusiness: '', + address2ContactTheirBusiness: '', + address3ContactTheirBusiness: '', + address4ContactTheirBusiness: '', + address5ContactTheirBusiness: '', + typeInvoice: '', + quantityServicesInvoice: '', + discretisationRateServiceInvoice1: '', + quantityDiscretisationRateServiceInvoice1: '', + rateServiceInvoice1: '', + discretisationDurationServiceInvoice1: '', + quantityDiscretisationDurationServiceInvoice1: '', + quantityBillingPeriodServiceInvoice1: '', + isIncrementalBillingPeriodIdsServiceInvoice1: '', + descriptionIncrementalServiceInvoice1: '', + idBillingPeriodFirstIncrementalServiceInvoice1: '', + descriptionIncrementServiceInvoice1s1: '', + quantityRatePeriodsIncrementServiceInvoice1s1: '', + descriptionIncrementServiceInvoice1s2: '', + quantityRatePeriodsIncrementServiceInvoice1s2: '', + descriptionIncrementServiceInvoice1s3: '', + quantityRatePeriodsIncrementServiceInvoice1s3: '', + descriptionIncrementServiceInvoice1s4: '', + quantityRatePeriodsIncrementServiceInvoice1s4: '' + }; + const valuesDefault = { ...values, ...placeholdersDefault }; // getValuesDefaultFromPlaceholders(placeholdersDefault); + let typeForm = valuesDefault['typeForm'] == 0 ? 'Invoice' : 'Estimate'; + + const [stateMainContentForm, setStateMainContentForm] = useState({ sectionsMainContentForm: [], sectionsForm: [], sectionsGoods: [], sectionsServices: [], subsectionsServices: []}); + const handleChangeStateMainContentForm = (stateNew) => { + setStateMainContentForm(stateNew); + }; + const handleChangeInputMainContentForm = (event) => { + const { elementInput } = event.target; + let valueInput = {}; + valueInput[elementInput.name] = elementInput.value; + handleChangeStateMainContentForm({ + ...stateMainContentForm, + ...valueInput + }); + }; + + useEffect(() => { + const dataMainContentForm = { + ...stateMainContentForm, + sectionsMainContentForm: [ + { + titleSection: 'Invoice Metadata', + inputs: [ + makeInputJSON({id: 'typeForm', name: 'typeForm', value: valuesDefault['typeForm'], textLabel: 'Form type:', type: 'select', placeholder: placeholdersDefault['typeForm'], options: [ + {text: '-', value: '0'}, + {text: 'INVOICE', value: '1'}, + {text: 'ESTIMATE', value: '2'}, + {text: 'PAYMENT-PLAN', value: '3'} + ], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'currency', name: 'currency', value: valuesDefault['currency'], textLabel: 'Currency:', type: 'select', options: [ + {text: '£', value: '0'}, + {text: '$', value: '1'}, + {text: '€', value: '2'}, + {text: 'Other', value: '3'} + ], onChange: handleChangeInputMainContentForm}) + ] + }, + { + titleSection: 'My Business Details', + inputs: [ + makeInputJSON({id: 'nameMyBusiness', name: 'nameMyBusiness', value: valuesDefault['nameMyBusiness'], textLabel: 'Name:', type: 'text', placeholder: placeholdersDefault['nameMyBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'companyNumberMyBusiness', name: 'companyNumberMyBusiness', value: valuesDefault['companyNumberMyBusiness'], textLabel: 'Company number:', type: 'text', placeholder: placeholdersDefault['companyNumberMyBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'emailMyBusiness', name: 'emailMyBusiness', value: valuesDefault['emailMyBusiness'], textLabel: 'Email:', type:'text', placeholder: placeholdersDefault['emailMyBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address1MyBusiness', name: 'address1MyBusiness', value: valuesDefault['address1MyBusiness'], textLabel: 'Address line 1:', type:'text', placeholder: placeholdersDefault['address1MyBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address2MyBusiness', name: 'address2MyBusiness', value: valuesDefault['address2MyBusiness'], textLabel: 'Address line 2:', type:'text', placeholder: placeholdersDefault['address2MyBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address3MyBusiness', name: 'address3MyBusiness', value: valuesDefault['address3MyBusiness'], textLabel: 'Address line 3:', type:'text', placeholder: placeholdersDefault['address3MyBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address4MyBusiness', name: 'address4MyBusiness', value: valuesDefault['address4MyBusiness'], textLabel: 'Address line 4:', type:'text', placeholder: placeholdersDefault['address4MyBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address5MyBusiness', name: 'address5MyBusiness', value: valuesDefault['address5MyBusiness'], textLabel: 'Address line 5:', type:'text', placeholder: placeholdersDefault['address5MyBusiness'], onChange: handleChangeInputMainContentForm}) + ] + }, + { + titleSection: 'My Business Bank Details', + inputs: [ + makeInputJSON({id: 'nameBankMyBusiness', name: 'nameBankMyBusiness', value: valuesDefault['nameBankMyBusiness'], textLabel: 'Bank name:', type:'text', placeholder: placeholdersDefault['nameBankMyBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'accountNameBankMyBusiness', name: 'accountNameBankMyBusiness', value: valuesDefault['accountNameBankMyBusiness'], textLabel: 'Account name:', type:'text', placeholder: placeholdersDefault['accountNameBankMyBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'accountNumberBankMyBusiness', name: 'accountNumberBankMyBusiness', value: valuesDefault['accountNumberBankMyBusiness'], textLabel: 'Account number:', type:'text', placeholder: placeholdersDefault['accountNumberBankMyBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'sortCodeBankMyBusiness', name: 'sortCodeBankMyBusiness', value: valuesDefault['sortCodeBankMyBusiness'], textLabel: 'Sort code:', type:'text', placeholder: placeholdersDefault['sortCodeBankMyBusiness'], onChange: handleChangeInputMainContentForm}) + ] + }, + { + titleSection: 'Their Business Details', + inputs: [ + makeInputJSON({id: 'nameTheirBusiness', name: 'nameTheirBusiness', value: valuesDefault['nameTheirBusiness'], textLabel: 'Name:', type:'text', placeholder: placeholdersDefault['nameTheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'codeTheirBusiness', name: 'codeTheirBusiness', value: valuesDefault['codeTheirBusiness'], textLabel: 'Code:', type:'text', placeholder: placeholdersDefault['codeTheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'emailTheirBusiness', name: 'emailTheirBusiness', value: valuesDefault['emailTheirBusiness'], textLabel: 'Email:', type:'text', placeholder: placeholdersDefault['emailTheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'phoneTheirBusiness', name: 'phoneTheirBusiness', value: valuesDefault['phoneTheirBusiness'], textLabel: 'Phone:', type:'text', placeholder: placeholdersDefault['phoneTheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address1TheirBusiness', name: 'address1TheirBusiness', value: valuesDefault['address1TheirBusiness'], textLabel: 'Address line 1:', type:'text', placeholder: placeholdersDefault['address1TheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address2TheirBusiness', name: 'address2TheirBusiness', value: valuesDefault['address2TheirBusiness'], textLabel: 'Address line 2:', type:'text', placeholder: placeholdersDefault['address2TheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address3TheirBusiness', name: 'address3TheirBusiness', value: valuesDefault['address3TheirBusiness'], textLabel: 'Address line 3:', type:'text', placeholder: placeholdersDefault['address3TheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address4TheirBusiness', name: 'address4TheirBusiness', value: valuesDefault['address4TheirBusiness'], textLabel: 'Address line 4:', type:'text', placeholder: placeholdersDefault['address4TheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address5TheirBusiness', name: 'address5TheirBusiness', value: valuesDefault['address5TheirBusiness'], textLabel: 'Address line 5:', type:'text', placeholder: placeholdersDefault['address5TheirBusiness'], onChange: handleChangeInputMainContentForm}) + ] + }, + { + titleSection: 'Their Business Contact Details', + inputs: [ + makeInputJSON({id: 'nameContactTheirBusiness', name: 'nameContactTheirBusiness', value: valuesDefault['nameContactTheirBusiness'], textLabel: 'Name:', type:'text', placeholder: placeholdersDefault['nameContactTheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address1ContactTheirBusiness', name: 'address1ContactTheirBusiness', value: valuesDefault['address1ContactTheirBusiness'], textLabel: 'Address line 1:', type:'text', placeholder: placeholdersDefault['address1ContactTheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address2ContactTheirBusiness', name: 'address2ContactTheirBusiness', value: valuesDefault['address2ContactTheirBusiness'], textLabel: 'Address line 2:', type:'text', placeholder: placeholdersDefault['address2ContactTheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address3ContactTheirBusiness', name: 'address3ContactTheirBusiness', value: valuesDefault['address3ContactTheirBusiness'], textLabel: 'Address line 3:', type:'text', placeholder: placeholdersDefault['address3ContactTheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address4ContactTheirBusiness', name: 'address4ContactTheirBusiness', value: valuesDefault['address4ContactTheirBusiness'], textLabel: 'Address line 4:', type:'text', placeholder: placeholdersDefault['address4ContactTheirBusiness'], onChange: handleChangeInputMainContentForm}), + makeInputJSON({id: 'address5ContactTheirBusiness', name: 'address5ContactTheirBusiness', value: valuesDefault['address5ContactTheirBusiness'], textLabel: 'Address line 5:', type:'text', placeholder: placeholdersDefault['address5ContactTheirBusiness'], onChange: handleChangeInputMainContentForm}) + ] + } + ] + }; + handleChangeStateMainContentForm(dataMainContentForm); + }, [placeholdersDefault, valuesDefault]); + + /* + const handleButtonClick = () => { + const inputsUpdated = dataForm.inputs.map(input => ({ + ...input, + value: 'Default value for input ${input.id}' + })); + setDataForm({ + ...dataForm, + inputs: inputsUpdated + }); + }; + */ + const handleSubmit = () => { + }; + const clearForm = () => { + }; + + const fillDefaults = () => { + /* + for (let i = 0; i < valuesDefault.length; i++) + { + + } + */ + }; + + return ( +
+ {stateMainContentForm.sectionsMainContentForm.map(section => ( + + ))} + {/* */} + {typeForm} + {(typeForm == 'Invoice' || typeForm == 'Estimate') && + + } +
+ + +
+ + ); +}; + +export default MainContentForm; \ No newline at end of file diff --git a/src/components/MethodsInput.jsx b/src/components/MethodsInput.jsx new file mode 100644 index 0000000..c6709b8 --- /dev/null +++ b/src/components/MethodsInput.jsx @@ -0,0 +1,20 @@ +import React from 'react'; + +const makeInputJSON = (dictArgs) => { + const {id, name, value = null, textLabel = null, type = null, placeholder = null, stepValue = null, minValue = null, options = null, onChange = null} = dictArgs; + return { + id: id, + name: name, + value: value, + textLabel: textLabel, + type: type, + placeholder: placeholder, + stepValue: stepValue, + minValue: minValue, + options: options, + onChange: onChange + }; +}; + +const methods = { makeInputJSON } +export default methods; \ No newline at end of file diff --git a/src/config.js b/src/config.js new file mode 100644 index 0000000..900e126 --- /dev/null +++ b/src/config.js @@ -0,0 +1,77 @@ + + +const getValuesDefaultFormMetadata = { + typeForm: '0', + currency: '0', +}; +const getValuesDefaultMyBusiness = { + nameMyBusiness: 'Precision And Research Technology Systems Limited', + companyNumberMyBusiness: '13587499', + emailMyBusiness: 'edward.middletonsmith@gmail.com', + address1MyBusiness: 'Unit 12a', + address2MyBusiness: 'Somers Road', + address3MyBusiness: 'Rugby', + address4MyBusiness: 'Warwickshire', + address5MyBusiness: 'CV22 7DH', +}; +const getValuesDefaultMyBusinessBank = { + bankNameMyBusiness: 'Starling', + accountNameMyBusiness: 'Precision And Research Technology Systems Limited', + accountNumberMyBusiness: '40168366', + sortCodeMyBusiness: '60-83-71', +}; +const getValuesDefaultTheirBusiness = { + nameTheirBusiness: 'Contechs Technical Resourcing Limited', + codeTheirBusiness: 'Contechs', + emailTheirBusiness: 'account@contechs.co.uk', + phoneTheirBusiness: '01268 582900', + address1TheirBusiness: '2 Sable Court', + address2TheirBusiness: 'Southfields Business Park', + address3TheirBusiness: 'Basildon', + address4TheirBusiness: 'Essex', + address5TheirBusiness: 'SS15 6SR', +}; +const getValuesDefaultTheirBusinessContact = { + nameContactTheirBusiness: 'Simon Bant', + address1ContactTheirBusiness: 'Jaguar Land Rover', + address2ContactTheirBusiness: 'Banbury Road', + address3ContactTheirBusiness: 'Gaydon', + address4ContactTheirBusiness: 'Warwickshire', + address5ContactTheirBusiness: 'CV35 0RR', +}; + + +function date2str(date_in) { + return date_in.getFullYear().toString() + '-' + (date_in.getMonth() + 1).toString().padStart(2, '0') + '-' + date_in.getDate().toString().padStart(2, '0'); +} +function getDateBilling() { + let nowTime = new Date(Date.now()); + return date2str(new Date(nowTime.getFullYear(), nowTime.getMonth(), -1)); +} +const getValuesDefaultInvoice = { + dateBillingInvoice: getDateBilling(), + typeInvoice: '1', // services + quantityServicesInvoice: 1, + + discretisationRateServiceInvoice1: 'h', + quantityDiscretisationRateServiceInvoice1: 1, + rateServiceInvoice1: 23.94, + discretisationDurationServiceInvoice1: 'w', + quantityDiscretisationDurationServiceInvoice1: 1, + quantityBillingPeriodServiceInvoice1: 4, + isIncrementalBillingPeriodIdsServiceInvoice1: true, + descriptionIncrementalServiceInvoice1: "Contractor services - week ", + idBillingPeriodFirstIncrementalServiceInvoice1: 1, + + descriptionIncrementServiceInvoice1s1: "Contractor services - week 1", + quantityRatePeriodsIncrementServiceInvoice1s1: 40, + descriptionIncrementServiceInvoice1s2: "Contractor services - week 2", + quantityRatePeriodsIncrementServiceInvoice1s2: 40, + descriptionIncrementServiceInvoice1s3: "Contractor services - week 3", + quantityRatePeriodsIncrementServiceInvoice1s3: 40, + descriptionIncrementServiceInvoice1s4: "Contractor services - week 4", + quantityRatePeriodsIncrementServiceInvoice1s4: 40, +}; + +const objReturn = { getValuesDefaultFormMetadata, getValuesDefaultMyBusiness, getValuesDefaultMyBusinessBank, getValuesDefaultTheirBusiness, getValuesDefaultTheirBusinessContact, getValuesDefaultInvoice }; +export default objReturn; \ No newline at end of file diff --git a/src/download.png b/src/download.png new file mode 100644 index 0000000000000000000000000000000000000000..7a5654284132065eab7a9cb54879b0ac3025b82a GIT binary patch literal 21953 zcmcFp<8viWu#K~^ZQJ$+8z&py+#B1rH`*i{+t_%M+}O5l+qU(7^{U>V@cPS4&xff~ zeX6?8)R{jj$}%X3goqFj5GZo8Qfd$o&|nA%NWpK=|DDkMV1xW`fw2%*5{H1OiA8!h zg8eUtbWxL$fT)}#KKXBduA->%L&j0@iY|Y;A3gkB@J5cGk?yY;JCD zadB~adb+Q#Z)|L=y}kY8dvbDeaB#4!~Mmz9-eWMs6qwk9DVF*Y`ijg95u;WITgWo2cBfr0V$_0`eQd3kwdV`F=LeKjyJ zaCLQ+kdRneS;5E0S5{W0qoZ?ja*~pgf`x_c?CgYxhsVLe!N9=y{{6eSxcGmCTv%AR zy1FhaD?2?swY9YcgTbn*sx>t=q@<)pMMX$RNaWn0eSJMNG}Oz> zD?2+oA|k@x-aareaBFL;zP_G{it73Kd1`7ZBO?P24o*{3^YQV~)6;W*fB*jeet3Ae zp`k%YNWkC!S7KsfPfxGAyZhh2e+vo9WT_f1}IeN))2(=CDuf)B7kaPQ!6;BP=z{ zpQ>`mNks0{2^!+}KfeAzkj2cMR_?E+mEzCsy(cba8UgXHhdb z5zm*0EndLFR=YsyP?S>(7ylCjjVOgE1R@2htVBPCJikfw^YcMlv|_lJm$b3;5ANg` zxLu`7oKhx;)9(YB->5su!aZ_nZl2J19b`{<$esg*9cI|C2R4TvqmXO)zncq&hhl#S zMPFnbSh@3br?=+11Lm~l{L!z0)S;J*{Y1qcj!tm$) z4$n_dBA++!@E=FML7vpxbJABPOnUL{l=jUp94okjy3F>viBASa3+-Patt8#2_91D$4B-_HTRH-`*aHgEsTzq`Le3 z%*Xh-ZX2QGGW?ICpei>>&L!LGX=`vCk1+C|1Ob9++Cj91*k(BPvzy5E04T!LqC9-) zBBopj5V40WR&!6W8aJ~9klSA~LY{HPXOb4O3pL6ZG!;_pIer>XNLxe|3Ihp(xYjB3 zw75s?+*YA!@0eyB3NUbXctqdb9`rsgo;XTGk>*eXJSQe%0OcUHpmPYHq=NHcyZ66| zQK)6AZ=+(v(o>?HZhAs%S;nbSn=*Vdd|^7AR#>5SCkTpdYgoOjl^Zq@R9f!3=|4f} z?4O_oy$%}^FXKE0 zyb@aHEbfO4Bkfh35gEe;%9>LCxCiUBZ2kljR_g7fyDcr?;*s2U0-O_nd=x>RjfKi{ zM$-*+tK`Hb*Efy(U5VW}`WSzGkk;1FF3zaYcH9HX7$^6Xa}|>fspj0FTRg$7vQvYN zwGyt=rA!D3U(6+7e!&4A@_}K8de?4wqTQta9AHWXsMSiJ3av7&Kh8shx>2uSZC1yPa74VAJ-n;35L{(48bd&VVI!Es z&@jWY5dc2kt4stJhl6+Jv>(D@DX|VkKR~d0e(c|%4&Q{0?UeYKPs;4^nPS1RsT4PE zmgyTQMo;yqB~hvpAhjN;=SvI|YC{U7FH5h+_+;jj@>pEDsj*G3soX7y z+*p@*_TdYlyoknegHRw$Xu0`Zt>%y2WUG;jIf`dSuOZg}^3$y#sSW?pZxObD1V%{a z=^1L@8~JNp%6Rr|7}1I?wt9nKkxkmD-P%T`9Y4f*1Q++gCdcZ;LTka7M~Vk@ch^)l z7V)x%qp;S1N{`k|mN0l{-SRruM{PV$XViyYJlb7$G>tt3#9~KpAhc?0wChw#rTHfC zW>#eS0ls__rWUrnT+48ooL87$gpqAG!dzo182HDG@p$&cNOM-lPfpoUg0g{8X&tkp z@ng|918hx(SIY_jwAr++l2azBPv$eS5IH?bWd-xosp>Q{su?P{+}q@5fPWZJ?E=)z z>nxhh!{8}lFtop#C2BwOlzk;)37lB;_*ll$n6UIq>%RzU=|LQ^Iy1v(t>#k^R4v+K zv0GZQi*ItR0Uq~{w%DFC8Z3IEOp*chjPhq0&L`o)^m>3al8=9awVxvKHmvb~JDS5I zI#~)?_|S0k7A_sVbl;f&O`cjcN#ep$q8+kKO)Eh8tqsV7GZvXVG#5!S?6WpCgXk7Y zBcG`$ZUF?`GZoRvZkr6`njaHv9Id4oTCD08nbKm{2ZGr*<)^xi>Zx_AyEI-Im4s>S z74D<$?aaVWy9&8Ky0NAD*$NK&{U>&|mRnp|s$O~4wPo4`x*Gcbq;owI-x?{aSEa*L z1bh-TN_MZ6Xl)cM{OwPieGnQ9>vOY}Utbwkiz!94C71fVOP{WJmu zA)gdj(9w?Xei%4n*m_m3uR)L2+tV3vOP9>R3$}PNI-8%|k~HU&QO(e99G{CI(P%?` z%7>)Dxib7aDPmtq>qL2GIj~kmUM~1=wIrLC$(|1iluB#!c~n+BQnpB6F8E8w6%*v) zr4Bj?9TsG2-QC9QoB(Hyn$pC%WgoC40Fy;oS=oV6^?#U+g1~h*nvi7=ZjrMZ3yT?Q z4>{sxl>-0aBi}mGR9bwOlUi6HUb35DFf%QRb7P#0b4%20fZf$dcGHGUWjv$j;{;hf zm~PCu4b=d8?IFu>O~zH0yQU)#Q)zBS&0Trs*m;I>Xm1>$o@_f;czEXYHFB5PF&VWk zz{aM@wc2rRq@WsVn>=uaS=*v5#uNCsx3OMBYgkYd5Z{@?%yj60$Ms9+(X!U+q%n_Z zmFA2t*G~{YaX?sHVMR+>E?*1qLzG=8&DDIdY0IFk1=)rAUr9MvmN?;BT{G7T##lGz zKO3{qISjZgH`+JXMX4*vvi6?trnLO~2kvAuQ-XJ#t62w)p^PPHF1)O{>D(BD?wa)U z6xu3Mb4=M@;e9d=PbBVsM{#QD0;XJOJ+mZ}zqPSKYm_OpgCQ9=&QFUwt{$B02aol> zmoHtcG-M!wO2$sT(kn+kn>i6V9X zf{A*;qw|r2|DRArUFaBD#JoCT&S6laEGEf3bCR z4ladfZt?NWqp8a9EOkvs<|m$Gpm^(Vu!|um4RN*q%u#8>^(nLI=x6W`-HlCw6$6be zf?5gvVIe*Jip4IcWNuFj8_0OKdAQ+LDXX!|yUMkIq~6+7pAQ|Ek{%(>M*CdhAEuhJ ziMPm`)BwXEL(Y(s7|6KJw5+KXOuS8grc-`%|2Hl}kL zuP$x%0xv2G#Pogzl+M;B{B1bOj&wbu+Lm3di}e~{^8`9ckt`ZSk=C_kD#09-gxsHF z26LVC^JUdU@VuEdF#Me>KlUJtm052|QBIM$J9a3J9*en3 zSB5R=%H1ujQe0w9^=Q^RSygLo-0G}xqiKxI$w<^X#O7o~WndIh4*L6Aiz~et`THI` zzO0^Vk?c05(BL8+>-Ve@{(8OBcc(6%=robAG%|K1B2-!^mMdJkpM*7Z{w$loLwj~D z?%k7?m?HK^WO6Y;;9{)!mmeyq$WQ`EhxPPzp8er~H9|1-YkA9jarHb$B~1;XR$Uum z22mXCa+_7PJ%(uFV!yVUz8QBUqYz5w-EsW@hXNJ~;V)LjH^d~&RiOv6i@WjjvE`az zmp~*Xd>ZBU&D0vM+@m+YLo-RA#S3ox{p7O)+%s9L9Ch>7ryd97CJ*3+2wRfac6G|! ztlfJ3w911H$5(5ByVh^P*C^CIm9zrYil|0|+&s8DN;vupSTCEW_TQi6q9OSCa#oR# zW!ak?<-%fYT!yMT_3eN$0dDRNsn}(!-tg>8MeiZvOma6)>g()>{8NHC5ShwbeP1lf zqN^Lp3yh5gFm`+xYSG`O@fk9SbwZn&58WgJ5bAw$-K!Nk|G|BHE0$&09RME<$t@TFnQ@RyYa<+ z&9L8%75&vUlS20m!+t{h&7NkfeXAe610^dK*1=Y%Fq;)|cGtM$mmy6ijNr{hftgRB zp`Vz7Ga5VCgZc{bzva zCVF^X(z-Z{w?M+Ps%nN}rrb2QS*%yMsrB$ozwQ2%+d~cT!(H6`w3yBd!vW!N%H`9?6#Ub#qAQ!< z!?#K_Zj!8`{Bvgd_!3?I6E{|ob<63@iL&u10ofxe0#k;fk9%fWGNVeysDfsxm^p;d z*v-u-Dc?VA#l@FKUSdXE9h9~owgCJ5_)AcbcN_L@FHdmZ>&dh7(#aj9ftI~;G?c@g z>-+X_OH#_Zp$?Cw%kwt;aHJo`j`P}TH#W|rBn};^coC z2h+UR%Qa_XHgkidO1qpo#U_H+*;(tWy-Q8o(}(w~o-MrEBrIe;kW)?D$tOI^q8$rU zB%`X1F3sQKe+^_`fA>s_qnUK1mRWYbZS@i-68WJ;6eS{0-zGJiK=h;T*NgS`KkvDm zt>tD{_mc-RT$+&8g`JsOS-bjLI~>#qAxN4dIs-*M1MJj|4E?rV99I_3lV)BGJ?eai z_nw-Ql34hqqbpRDEFu4$-j_hFyR+cf47wpbL%sEy-_dlT9UG#`?nrh^G=8o>t7*Gj z6-)gvK6={KrDChqN;-wV4(G1`L^)R{4ZY7N#ax>0(NmMGB01PjY84BNJRyyC*x^FD zm|>ijB;yzlrp6yT_>&xWvq4-fd_O+R71c9P|^*B+OaoH08vbzdR*O^9*W& zZm%q?t*x|q?WrXmYjo54D1?{q7WUO`>;;HJzjJz1iey_vg8+Tryx&xV5RLIVhI#jz zI(F-sf|9?-L++}u_8i=LSH+BBp82nto!%p;_TDA$UZ1{8@;f6>2_BvyxPK0&E~S{9 z0Ayrj_GMdIQ2+lvJu;+eNR+H=M~ zXjF5!LN*koOoYflN{<(%C)&|bqAc15&_|@gwg32%`3tP4*`VoKZZ`tc$ z-)jU51_r0jZse2)p)?d&;lTT~zd;GVp4R#Y{3>$|99!So+(iEqa@7?74C`9BMt zMKmT-vTVe4`qY<`u8=`%{OxlL@8eIk0`dIv=H2?y2VfE4B(`78iNW&PQcL(bx-`9G zQ-%R2X8YS{G(z>eR^Gg{JcfaRrU$Ibs5NW+EYV=QLX}DSQK3}x$kOugor1ln?D%KV z>wc1cYgY1FUSv?2PlVOSp9n<8;qS0`RMKxDNlYwfIXlM_f0o_JZCFB6_~~t&RwEr} z{Fe@C4hIzm-5u<4MSPxqT?_ta|3m)jNz082X~0S;bv zkqyBzGrVu|j>rPm#t}v^8f<7nuR6cA#$N9-l87I}#=rb38J1(S8nT!AP|Ar69`Zm; zXQy5jk(t6Ycx43Sjd%`&Pz}vLK;_QO$OcU*VlvrMqSJ*0oyr9fYac$$6nSyCTtnx3rTo1Q!0I+qPjD@5ez;S1Nb)iJ-8_S$g3{jOcwGW z%A2ODNiVaK1!kJG^N^jCL~L92#7O#(uNhDew#N(Gx3}X8g>(2(tjr7_mCT}t<=gbp zm+t%ok18~5$>|9>iS*dTvyz-sHlDM#rf*;<1jwL{rZe`Biu21e zo^@&zq84Q45w3_Xj+N9{VgbE~)4E+2t&zW-b}p}fb#%kcdD=j(s6A47pbN^AcL5{` zZnkC4@z1zfpiMllD!ra4zcvEy*LZ2dvDy=3sGA^2? ze`kR(@C=o8SwN>65h(h*D%Ocmp1gYONI=SA@$u8Yr-dnKCfl5S=GnV%mZU{Lt|Pt| z{wQ}Xji=v~4=6stbJ~*Mhk;^KzKL4?-!o8^Yk2qXl||dzOITW7`6)KIuG+x^tJIzP z!KAtep2yYoGn$^qhMigsFTsJjh(^)!=GKLYDGpi)ZEJemK}AhrT!Lp>QsT?# zUg^i;03Q_*)bB-&r7FE^>5{b*o&_3ZvMV)Pe^sF71=!?Nnc?jn1=SX?IAgJprV*5P z9yrRQq-JaAVdb-bvf#imsP%|7y6t8FDP~zdNDjfC>9Koz)|);*doq61wDmCVoO)V) z{vOwya3%c%7)7SBE4qd!vwju;2I85br;#dR=)=H{({u+^D(M;z^xiyQ1LQ@C~YKvLWdD%bv%ttNS0la`MP53nGsPEp_+ zJw|m3Zc{Q)r1d96SSp0bI#GB|&FUbx+1hWk>9HxoGvXO-^S)PQDbU3D672L{PWS0Y zCroM~0}j=3?OTQAcIxi3il(IFrB{sclD=gJ^WeCM1w1HqueLS>EjZ*nAGV!@p_Tml zyp>QN?FPxG*(7A#|GmbZ|hmWzDhQjVtqxz}&5%#tn!8_M6=l z={YaThV#mXSeK4#{rJ$xmJ~#RI}RK==|9XI-Stv7uq;9y;H`djOrnXYu44xA2@=*F z>R45~7Dzc%za}#Gh1^5<2a+2V-}SIn`Rjba*-WH$Yf+F@MEKY${U*`S62XlNgbI0f z_;F)aa9AQqq#vmhe|^xl*g1|!XDce^b~D>&BeL~zuUW?kTzry(6V3^Gc8iLYoC|xI z?D1A4JrFyrWzGK)Q*XxtBni%P9wLxqu9|mZnZ9>6IAFxm)u&-8M=|qBRsoE^gNvEvCUUkSr z3mvp^&3caeSu~EgjpoSk)EK~{bjVxgk!I=Aq>Ej>83lT>#LXvx$oE{8v679D%UAZc zcS~?0y_M~{Yo$=&OTSiMm|Uc=Td2v=2|zm}DOVpmW&QLniFJwmW@#kd|IxauWDm*I zNmEXD!5Yo5>OCb=7LS#sG*JfODBx9H(WMh0N^jyLtOLv^H1R@aU76#o5du#q z(i%F9mK;k<@76eXm7v|e1;KxgNHW`;vZ5p$xRp+rYo0pUF`Rx+Or2$RXeOCS#{1FW zs^3gv#=es)gdo+fux)Jy;J=sJ)h<4eP#!fVMX7S@UEdJ`5k^OC;Y*|w2N^x#FRF_I z%tfqCdVEj-vrvm$2B9Z)**R5G?QFLQNrc5_H3Y{1-cJL zytJsESD$dlS2qhV)GQAka zGbZZqYiPTP9yKfihxDXO%G8~v9ojBvHE755Rm3mX>o%N}upqnF%f!dn=>M6ZW~MHW z=1zArU5&ueQDw1rkmc{Sfa@@u^cK#=xz`VLdy;0zV;T3(L>qI!6;>C^)d4Ze4(JLQXUMO znUR!OmJzo_NJT7kpJtQaANfw!DIr}^%*TK2t-`2BMx>#H5%SLSo6+!f>SkD)mc8eK z(E)Ul4+}m<_rnIoMUCR>LDxm0q8x=%< zA9EgZWwJ{=mp`({eA|L_n9Tj?rkc>19w?bN@Y<`xJ z`Rd)%P!q1_a)T$pakv^~5Nyir6Te)9tA zR|+m?A^pCq6FK1A8m)wztq#3=Dir~)?pwmO5wE?4*pQ+ka?gq&Cl9X9OJ6VGpJu8F zlZY1NVp-!tww17B&&R{xAewc~zYLe^hXG$w`E3E)0&Cr^Pipvr)5XTG0aoS=Giz!( z<~f^sUKznE?bYh5f&=}02eQvKn6)|erebeFeAn0xA}HET{N0sax)FWc z(S0S;TAg9>D4rjCfjDW$I%ztZ$06Vhk-hUn_A7m{YSh;g6f;I+` z5rcPo)+Pau?e_7;J;>)_u}x;(fhkq1TU4Fe%OWIpJpHrLh=4W{@aSpeNe0f%wBlwG zbEAMfiXDc{S`WwG0Ko^Q+azTcyMb1`LMq{_Jf>?F)23rt`vK!LtYaKO9YiPd6hRX?``x@ zdTa}B4XUj4^Tzje@YH_ZMKQbi*qyy==RkYb?H*ahSP4q{o^J6>Mn`LyE_0-CjFm8tb`YShKnT zt;LB!P^;jO2%lO{1}+{z4ZXw0i@K{zr7Qexw?~;V$~Senazc7-7|lv zu1RP2>+K*t<@J%+;*ZHd*y>Ds6*#^c3c*CEPH>OP;|E4xe74wGk+ zKTkQ2J|PxOAee5`27t}99pyQ`NFM_B95q*5KeI!8BzOlu$2J?p8tlw=2+sKAq*FK> zWt=k3<*jxviXJaTIc{9Ok9J0;W6KM2|WNwrU}&7 zL_ij*sB%&RltmQDgpQRWa!T3GWrFPIGT~_%XhDw8TFoAMODdrFc&iZk>9MtZ8q81I z`%_%+o(z=ZSNvFFcWQKS>!~{|({~1~;vtMtW^|c%+ zV_gm|;fZFD#<1`rlSEpiZzyYVDRwbRsf?b5+%@>5(cK?5BAy|&FB?(5-c;rac*h>&hGB4F)*>f zFd|2e=@+wAz8LL_SsuQzbH zYF#*-0udavfV@cAbh4b8HRaY1d$3E1D-JN)P+i`4NjINvg0YG0hp(>NQgn&pYDI$K z-5QtIpjpX^<{<+B@MV%1*RJx9T~6|X8w|i=HppGKbTWo-n~&WTKaFQEM4%U|uUn{v z))0s2U+1{YnW_Fp<1!n91U>GDj184!da6w#0KaYMw~iey*KZUt77XLR#I%BkgkIrr zl_a|s%<)?{mLLF9I_kq=$Nuri8jXg#C!rrGbpg07Z$8|6gcb8Pc>A1yE{jQbJXV_JXmI35xW!Y{^o~^jdnMw z_*c?SO_aS-8W((o<#1!ihSDohhSAlvzVMeS4vZ0~nNeId|CxO|I^1i0YMf_EzdItf-csAV z4O^hkd6v0JE7S2iJ-5juiSR&;CjKCCS|jbR-`T={2mI%`D|IdMCf!(p_%JDM9_FJ< zl};~u*$)sE9YDhoG#pa?$-v!`x?pTBaTdJzE^H~x79URUY}0$;QpFx_ML`c_hbYrB ztN&;eu!LsyI)YT6yC{?4?}O0l0~whhkEPMgfj8wt-7J#R+vG6{Mds?ll*)FP9)Nar zcnLTdFC8*t^^I`m^_LZ(zbfA@75^ZqoeCTn11xYMli|}>$U)iWY;4R}hpUV_;W2CO z`?9r-@UYQaK=;e2DL(aP^B&K8Rm4ajxA;(xZD5A*e0-S6Yi8itl1kvFzE&9E4+(vDL5H;@A-Y7{MyDSdpcqt@!5towYC z`aGCIOyt+Tzr{WF`B%tiGy)OHU|`FejD9MLlunYmdKI}wIGdscHB;Ww?cupsnr$a> z&MxXVlLF`5=(-Hd9j_jSa~#$~6yAlD4ViWsj^B>ngTZ`xd^9g6n|5YGv|6m298_|k zmHU&3=Ush6G;3R{Yr26aUz3e8RIRu)V^G3)KWHXnxz;PM^fQ|x9Z751xpuv>ZyHyp z@jc2djt*J+Ih9IeGgyathB3ZNztXr}h&;|(Pm=cV=~f0P_0Ke0?&wvSc!ND#!DHMz z#jKtnmpMD9O>`CN%_o2dKDuYi^&1WAFHeR z{e?xyLxG~98JO`eK+lRr7jaBOan*gu^>}yLz-314!;K?+lF_jFhP;5o4z|`@0*yzKTN2}#8B(H4X2uVb z(Wtl1;m%xjGcId1;|&xb?X|SKUK|Ixc84Ix_D6wxhit7eVHNiAm;bco7;Xl27eq>x zXUc|B>00|Fcg17JkX^>^AL&JB>7QZ!u|GL1*&#pu1&n~T-;ic7sLQvMOpC9mgWTFp zo?}?+9cJj8`#2K!D>mNr@=8ja1{&tO=xuRd)n%|@*uIlja3hcEa^5ly{#iXNK=}=$ z%&>OiHJSW_pew*98;RkC*u(HnZrNkX0kOLRl|b5S#1qz#UL?%DZa^RMo>t-7ZDD}tpE<_elCaMDYTbd8(#$Deuis0arCDmvIs1~aDg zTl=A2e1lC6DLGqfFg5wX0&$GeLbR4NZ?HlMIC+4mHfF3<}ASS#$_9WDAD_BV}mhga&KaO?N+7FSf5nGv;M7e7CDQLzLEp)x*`t9v;f10pN8^1=mS!_wyNa9LDBW|x&buq=laftgvDmu+ zUqY_WBhFC?26oGzm-pdym6dONUFH;x;a?Si=jHc3?GOF;RH3ywEH7O01~sUNVB7tHi#R7%ccjU2k%cR9RQL z)hI>U8ldTkVd5XfF_Jej_CTi}D--v9gU;tnm5ZN4zt$ zH*eoB9Xf3(MV}*LIU_%wRK3|EE(hznt3^_unTxe-Aa|UlqTv%c5#@9Wsdgv^-BLG| z40rS?>5S|8$K^f6pG=w#E>piw3cR{!Y%N(vu{&n8A1Jc-lI%=8(P>0CtfYt>`kXua z-vI9O_at2tOa8&Ly0}Jdn2V8#8Vi_eKvrYaWF!(yJr ze2`G1_0+%G8~&1>%J?EA)mVyC4uFC&{Z|@J3hM`8o$$x!;)P4=+h!+4AOuJZ_-B_Y zHna07#~|0m|LEY`iI?XeB-^NH-I!O!&j`%;qe+A*2*qem{aC9-#Rn`5(*Oa}at|@8 zg{3>|UDjc|8sF^qzg#L*BnExh-|1>&NM;8T!aTsIwz_Ag_QX|I3+wArfs36yS*1}~{6Dg?i zVMqODGB2Y&(o1~VCYHLPJN53#qi5QA0Nmv2uy;b-7yV$iO?9!)8P|L8t(`M1eHqZR zhNs2zRlk<+NC9K!+Hbjz7Tw=BfB&%3uzBs8OxJ}0W5!=xTg|%?Q#UOX7w(2?LUU5oIhi&HXJ|7n?)wG?B+llH# zbnd?)b#xXUyXuxEq|C-nOey(K-_(w|xfth#atg&$T0W`Z0MZ6F-{{~J>8R~C7+=Wp zXTF+{0m{WDR&@>*<%9*6gps0r3nN!)4QvR@d5WZ)oFWN`3j}y%<7tZb7hgrOcAbAo ztILGQ$^7?FS#D9|NV+8px95I&MP*-8=8sfifyd>>O}CH(eYtyHzu?c3^B?$TzGV$| zv^I_L1dn0mH=1YjiX1gCWKV6I$EGaWZmLcpjTWABo$~!vw~RJ3SQd}rKHf8JALC}x zK+34I|49Q}@G&SL)gTj-p;D5EN9Y=FL<2Nr)c|qiZX!5N%CaA!4_)i8H_f{FXmwj` zPd-$CA0PYjVu>PN1v?^V%aq*H_Ma_*r67M9OlsPG+SOv!TQ{5IX}O}nYwWTALK<}7 z7yezDEc@GF3#J?iFw0&&iqI^RGcseQk0yV7Zk2k03}+pj{IupJIE=d?U(gjKo#%@e z6KZ5DEqD93qwh0+u}kbXV|FDYIN2`~VbULNNoy_TjQdQu@`uq&G}*=d=S|cyQOj=~ z`0~|8V{nF8=r{eYw!lwaLwi^wk5y}nO`S%Qu6enAhiqS`S>eu8&WnV2gSR*443r(h zGl+8U%ZY!9yd$Gj#_*N{Tngnp=P&vjZs334fE&J8bscT^LLc1XQbFg)<+&_C4?b-0 zF4~qUw;@@AFXr!m*IG}V0aQBbb)9Gydg7-bz9yJT!BIEd5W|jKM?XNqiLw3LCSW2HfN=+to~I9N z!|Yz2V7L=M>+mrO%ZyXI$oq&am@|KutW`ttOhDBQKbAdTH*)FTGaRSowTbbNqF?DQ%ZA##dAP8PIjk16ra#j8 z>ata~3!V~DXHPkUVHpmHOJ+-4Ru#yF*h7luktK~djxq^I9vA`Z@uK>{JcZNCmO%~L ze{@ZHR>=SXXGwalBh)S1h@kD*1(-9txl3`A247?&#CNqIYD5{ziBW&mvzla+t7wx< zD-I)6X`R728O1jTx8}ACaT?8)?S^ksR4wRSklBi)tAPaI&U15ScXif3grZEpF2}i_ ztUeh}MW)rExyvH1S+p;P6}Mu7;7E8W@{?j)xtTDgOjK^|Z3rFKA~Z=QF|Ne#3ypwKYE}2 zA-H=Yj(v>c2NL*UwasHzHBg@@(egPt=TA94%^PyGNV<^RG%inkT~p zs2^0P-j2~#6A}&H|6QM%ol@>U2B24+b9f#t72FV|`altPz$o9EW;mb%)|p9jid8F? zcF$UU7c6T)t^SDElC}ar?E$1_@b9eVl2G zst9KW;IP*9S5&!S+n926*D9VA)W3T6RhLcvTDt1g_t+i^!&tfGQ58!In2Di4y%e$v zdPuYc#PyytWjR=ac?a!71WY0Wz~5sbR5%zX@98msP zKqySE6tWu2csH6Q{BvBime(euHFB7tc{&Gr8221hJtfOQaB*xz227{lQr&e_OFJZe z%FD_l?&$Ic6e{X^_~63cBkk{Ri_9@Qa=R2+qv)cv`6|lm^SG)*0ub=@za{wMC^tf@ z)Rg20MxZgws#dHT^d@F#iArRgX92B)8d$4Y8Jdf5$LYnhBd@kbmd2==#`%s_SLiR_@GxlG;`adWgbP`K*=+WSnmu&=}KQ|w=N zw}}##dJe~R@-Y}G{#(TkT(&VcVdh3emf?u9h(zOF|A4`SZspe(J*(j2PpKe2p0g4N zrX&uO3J6iC@#o--ev3NZZ1IhVKt~AFThsxz-%&NO3~nBDp%>xE^OIw5p7^l~e>(X3 zI^XO07tEMTXRNS#G*afnRE`};5WP-H-Dm)s%?SfZ7e4|2A}S7rHFhYkU#@n5B8}efyXQh-IO0TxO4n@pJT)$K zW~H*n3+lPL1n)E|fR(E@U&^ilG{vOUler60RpQR+yfGXU|5Iu5zx<6OK ztDOuk*%1%w7{9+?I(p2mddRLKWX=8=)Jis`a86%S=Y4M*C%9(TIOwIQYW70JxBpQn zzhqgWQ2hqTN2Y!7-w<3PF#(KJZc&|TS#rblA!&;Ly!#af(9-}kdGE&`*-G;o{)X|o zKQt+}QO@ER;fBl%`eDA}S?*R2kLNfRj7X9pYP zBYO>Xs`WGIn+Vm-bOTJb-Y_(YcuHR;1RN=il@T!(*mxx^JOYiGi>-~cmnTYKX!2Dm zopYcPy;XnB1{LdTo#0ex@6T&YiT7ieRF^&e`BkBqSe)qQ+moXS$#}FlV6{ zFU%DminRH93vBA-hb})GL^i&~W^`Y$`FLW4W&1gj1O*b7O=`wh6)Qy_hYK{)?_h5g z)5>3DRee8NZM`IoW)~vxyoxr$Pi!aa?I_@>y}!gN-@m`Klj1oE`#jo$8&gASq20#C%1NYoIx!dJ!XC3Ut0&Nb1G`(6WR}kJCF7(wi)?kLIJ!iFhPwgYP-B&=cwZ7TuK^gXyiL#n3K1EOU z=WdIk8(%u6OAV$a?mr%$%%N0=ShVpElRYU?8WcCQ!rpSSN!5g223SXQWp;`hk~6=> zfbxz#tOAtWXB~$c=m4Bb*H03MuM{53xm>RtOD$u*!UWCUzzyN98L_9AM6#4CPjs|2 z7oqI}#uDTnsf`ONVL4S7zfZwjS{_86rUf*T4CBA+FWz-T$ayCt$yweSVl1o<9bEw< zFjET4gnyk`K}*a`uLfDkO(h(*Xh?_Q(cNolLyAA(7Au2!a)lkkNhOm=@?_DBF&yB^ ze%pf!{iDUWy;)Rf?1v5xfNlJqRw^dsI`mf3y zpLjglT&uyD$+M4kARNN{!#%xu*!DQjf&8af|D@e+=@c{w_`{dhU}BocU?W?>)ML>_ z^M{bXRX(|VQc2(Kfi(O!NZ#J#qm%-M54WK=G6^rLar{%q$5LqWQ65MY{k9?N+ctC@ zL#RW5-Mg1h1Y7w5WN=rAS<&1lrOQ8ByX8}|J77zC>1^*$p5U9+uA6LFllZ7v=8QRr zvrN+vs9y!6nT!b5B*E6&jFu05Jc)V(uSUP}Ir9u0YgTpRjtxNzpX4Q%%`I`0_KtBt zhD?!AK7(l%8)wT!z84&Yp;&Zo@mQS8gR2r6!NT3P@KGyeM(mxl5 zRt683PKe7mQm_r4mxxf4?oR@qPNj6M%~CtlcqG{^(X3_J9;^b~ODQkx z7pwstToIf47Nh+&wc_{yn5#yHpI>^q8XC9==j|SzGc-$-uu;tt&ii3ZaAb1 zFE}yQiW?k;n&XL-#gKZIlph1FztQP;ft1a77txBJPjgXPnhurg6fXBN?Iwr}tiJ?U zU4ExNeNg9tcWc=H(de})r$-7taUnUj%JW@)1kdmgy!BjN3vs44X#90zHf_hkOGBn` zgDbAu6QtWy7KTg{>pm?jBu3@rzAdZYros9JLuF4$hw@X$%wfnTJr>w)cx*}l024(? zL_t*EF$AmnuZ3ZBbae?T76bb10rG=4s3(OxBoruk%{f=0pm#*Ja)Y(Xr|(E`5PRQS z->I1%obDM`XuYEC~I3 z>Z$#@!OFP&){j!GPA~E5Jlz5^y*p5HiRvxj%J}%hP@lsYq)IGA->)oAb(HnE0&cP+ z_r22~)UcE~4$Ai~%Z88@l0K#Tj^%lf_AklZ{%jL%RnixLnG(?=W^FTG=&C2jVsw4v zj!|IIb4J}Lx-@fkw4CBEt3B%YtnH7!mIT8sC*D8lLwcBg+-B!VX&51gYYQa_nv zbAs93NeDF#Vj?+8X9-JDIhRE<<2<>Bh`Ig*jKy<+_$PT7ag3zYTJ%9h>$P^8=@ zdHAKcW$AB$a)U*S`rsARkSdthtr2Y!kiaiv|6b?eJ=9qhLDCF-YUxKEgZe2hqq^&N zR^|n(rwRV2C|Ml%$d|ZUYBMGMwt)pYa29TA-Li4)^9yw88b)ZWI=VBLzPUSOb9Vc+ zth%>P@&kdq*+V-N)=AnKNLVGz0cK$B{IDiBP3AN3Q>tbv_&NLGmEj?&9qUy8MIir!-UL@1r$I71OpmueiRR4in!%wxDK$|fX<$LK0E=iD;|goEI`axJ)JUpwTcTd zR1fS%2t?U?yL@fJyF%U zJqft!)R!n|+S$!p8*eW}Mg%5W_}fnZwW`#6c!!5sy}O-T+Fr`(FiJHr5@Gt)+cw) zU8+3IhhbrTJ^yt2^sz_Fi?@!}%IKNPraJf@U{R4iX9Ficc=Ro+zgkA>aJs-Wk4tL5 z`^z<+fpsrRHfG@CdbK?EU2S6M`t|D*H>RpZ8QZoAX>leyJatkc5+Dq5^zq%7tE;)Y zgGXIhx&2qAvoN9b-7L}#jtYymxnFQU6Zi1tf^t*iu+dRO^D;EKY^kw4w{Y7E4~DV|dD?FiJIy!&zH2Jf->>SP~K z<;!(ukOyd102S@xPFX#jE07IIV@?&hy^iCQcwAb^($o}I>+T1|2q&Tcn@)L56Le5M z+rB^MMx43{YtW{hypF1oQZM(thA_cEQEy}=qh*-nO8`1`WJwC48Td(`Yn=<43Cd8l zT%77QC0(70d9jyABY~Tf_iTEb+)uazc$KuB4+mf(sXKXq-u7j7c;Y{|OW-hJs~knP zCH36c|;cER?F0>SrI1niTW}pWN-S=LFd1TKSI|No^5Y$s>eP<%e z24^E1oktI5vu6HZU(fYn^rt5>Qbabgk%2V>Yc?{lW?=me^&7P@Ja4qHMMwi4=ym)XB{ z?{(43w3-SpL4G5b08~#tdJD|$O>5jWQDAd6+l+V3IJq3?8riT$Yr!{o0G+#LAk zZUwReu)nNAkb3ZzU47}v(xKB>da|>$^E?=In?@Q8!2Za7cOtT0+nd6E$aK2?-0ZyK zn_h;j0DMXS!x-)~=|0HI_rEuL4XQ^j4_r%U?cFN0Q$L4W^4mv!XYNXOS}1Bs`Q6@X9e#jfaFwsE`m^}rD@GSF=g zd3j*ul8!VOfc*>BpoPxQ{}}jqw$GuLt|GR-dieQY7qWu>E?Zai%Jz3>zddvI%%SsD zmosPn@~@T8w}pYMppWm|7@bz2`r@LY>&6jYF&2#jv>k@5pr7fC1F3X7L27uquXCsi6N?Dm=k(DB{ z0>#Sf-y$nR8Vo?#Wwi)F%?dzI$Vv$%geoPg&=s-*<@Upbtdy!2S%s|Dd7NCJR&cF| znw6UB$x7_=*bD}W$+}|`qF!WWLe>gSFHlO>#fHt8ym_OHtj}F}?P301oL!*I?ou$m zdVSPp#9@}BjI596nT)Ld)nGa}04i)P1>3=Qn8hr@oLj26sx6E_{r_j|JOE*0 zC3uASuEiXanbm(QBWt@V??o|d$G{E~P$mx+nXqxyH|5H1JXc26WAc$Kas6SBbZjvJ zRa})%`d_gv%1qN;P)1hmM%5Iu5_=gZ87QNxv7)b6P391bJ6UyPeePOB7OmG;agKp9 zvWk+`w+N%eeSbn7S*NP<-i>KjAK@GWWn|SC@B5A;!Vv#n9apvEJ~tUNiT^{V1%QFl z74$fZy1u$DmNj)OGQXjatlC?b5Xy<)SgllyPTM*FdYV;3KVv%Rmy@j?c{q-M7rSEjn!aUE^GxoF6)Y}pWTwx9X01? zl#*5Z$+Zc0Z07%13A#Aru|v??tmqH9X)=)mSKp}Rs`lD+L@h3o1}-;*AuH&8Td(+H zMH7?lEGQg6)=y6wc|&v+)YhEZg5$S z6N^^m;LFZv0t8sl8yFwhx~S{xfA@)FQ^(}Aq@t{eYLEz<%;tAG`%4wL3VKaeIftk6 z;L4WCE!k6{@mN!mmpo{4=up$y-aGU~yy6OaMpz?QtrdO!iSG~*S(!b$sVT}uSEy=I zhxp`2eMOY52N_ojKzLl0@5SkN8uyq8tR^>IKdq{)C*M@5D9H(DmVf(EFpFNVz*f*R zrpm?opC5=Rw_hAet0bu@OY2^hP$r*_;9HHmGND+3te|&NV37+xy6-dD)tfqu@dZs` z3cgDyHwmMrZC`&VpAxPZA8)n+5Y`!+{!>$$=)EeZj-2FUi6g!( zr{5SKOwC1@1tAQo-EYSFcdl(xPAo>brM#<}mb%fPmeiF|o7m2k?e*X4fo_lmAUsqm z!41ZWQCYe3XVKYU57y6r zwL`Xi!YMO3wYfjPmDKuyXAXB9hl;GbM{q#HlA>(gPx0kQpUaH!@ zO@nuA7_&`68ZXAQ{-Auz<+f}c!No<2anrVJ-xtLI0AWK^YhrC$77?|ZNPrm=H7jj6 zkF~zxi&vz|gRz#DBM0U=EEx74Or-@NM3})$HGw0`Hb>sa;O=Ht>n9SM+!e=9IhW0_PqVQUEdA)orq^S0b7Nzt0SFOuV{>0X&fo62o=zuX`DAh; zna?LDCXxVzh-tARCnid9@0&0C-PBX(GVOf6)XukKk->JU9m_@l2obgT;9w-uE|v1h z!RU!TR&^|!PqqhR?RI1^CO(mv5VkZ3K!|8}e@4VY9ZW`wr}|UXw6ruH>s-J(u14fl z41n;^F*Ons%TxRuEJeINOov-uJkV1RiwneG00=L^Iu$?Kk!GLmI33T5gOAs;@tF7u zWDP!$H~`@!7Oy3;kytHWi7ywL~US%Vsi(MDPy)go=eX>sY2OAEk2kpm+MngLjZ(~srqhG#FknnCv>gJWU!XY zMzXK_WDhtJkLGIfiY2aB8L!sf9a`Ji*jNA{e29g)u`xWnR!+uhiCjjefkNCwBA)IC zSBo_-lda`4QdBPyD^IS8k7F2s&>}*~#_+~kIg-oOanU6PZFTk@GUmT2A?`rFg;16bczH7cIofYr|`^0Q3;~ zM6-~|d7f0(JFfQKRpF@T6}(&_TFcij%+6i_pqF?z6Y-*Q2^R{5TvO@2r9>uLh(>dT zW;8M}xprZ4XcB;4Vs>__?KPubH0Ozhtniz2$GoCA%4W1sEX1aU-c3%`akB>W*qxlA zcSFfsu~{rMo5g0XrR*yv6!QUIYnh1 z&!y9abg|iLmZpTN<+}I-KubDHd`B6ZwG?(twXG zS%qQU4_AELSTZT$zF!YxDs7?Y-@&G;Oco2b8~WW<4=mU&jbS&ISyg3H-F0P z&hG$4OqNw?=n3n*oGf#GY(1ceDT*wUp(m`Ftf(l8sr9Y}6shvLv=u!Ly~uMJc@x^; z07bI7vFQ~IyI!C4rZulW-V5N9>i<3w z$m^dQR^YCTe4pKg4+FU4#2YgK00000000000000000000000000RErf+~tY=8(1?@ P00000NkvXXu0mjfh)VE` literal 0 HcmV?d00001 diff --git a/src/index.css b/src/index.css index ec2585e..ec418ad 100644 --- a/src/index.css +++ b/src/index.css @@ -1,13 +1,155 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + font-family: 'Arial', 'Helvetica', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + background-color: lightpink; } code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } + +div { + width: 100%; + display: inline-block; +} + +/* Inputs */ +input, button { + margin: 5px; + height: 4vh; + width: 20vw; + border-radius: 1vh; + border-color: darkviolet; + padding: 3px 10px 3px; +} + +select { + height: 3vh; + width: 100px; + border-radius: 1vh; + border-width: 2px; + border-color: darkviolet; + padding: 3px 10px 3px; +} + + +datalist { + + /* display: flex; + display: block; + position: relative; */ +} +option { + border-color: darkviolet; +} + +input[type="text"] { + border-radius: 1vh; +} + +input[type="number"] { + width: 3vw; +} + +input[type="date"] { + width: 8vw; +} + +input[type="checkbox"] { +-moz-appearance:none; +-webkit-appearance:none; +-o-appearance:none; + outline: none; + content: none; + width: 50px; +} +input[type="checkbox"]:before { + width: 30px; + height: 30px; + content: '✓'; + font-size: 20px; + font-style: bold; + text-align: center; + border-radius: 5px; + border: 2px solid darkviolet; + background-color: white; + color: transparent; + display: inline-block; + margin-top: 0px; + margin-bottom: 20px; +} +input[type="checkbox"]:checked:before { + color: black; +} + + +/* Labels */ +label { + margin: 5px; +} + +.div_title { + font-size: 24px; +} + +.input_title { + font-size: 20px; +} + +.input_subtitle { + font-size: 18px; +} + +.errmsg { + display: none; + visibility: hidden; +} + + + +/* table */ +.div_label_input { + margin: auto; + width: 100%; + display: flex; + flex-wrap: wrap; + justify-content: center; +} + +.input_label { + box-sizing: border-box; + flex: 1; + margin: 1rem; + padding: 1rem; + border-radius: 5px; + width: 100%; +} + +.input_label.label_title { + margin: 0; + padding: 0; + font-size: 20px; +} + +.tbl_container { + display: flex; + flex-wrap: flex; + justify-content: center; +} + +label.input_label { + padding-left: 5% !important; + padding-right: 5% !important; +} + +.column { + align-items: center; + flex: 1; + display: flex; + flex-direction: column; +} \ No newline at end of file diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..4536cf8 --- /dev/null +++ b/src/index.html @@ -0,0 +1,2 @@ + +
\ No newline at end of file diff --git a/src/logo192.png b/src/logo192.png new file mode 100644 index 0000000000000000000000000000000000000000..d49d2284c9587269c404a66582d658e62614e944 GIT binary patch literal 14273 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

Em!oM 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 E1;^LCwg3PC literal 0 HcmV?d00001