diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 142c71f91ee6b299716b7fbc987849759a88bcc7..95b45b2680f090dac3a63844deef641246423a8f 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -2353,6 +2353,12 @@
       "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
       "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
     },
+    "@types/raf": {
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.0.tgz",
+      "integrity": "sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==",
+      "optional": true
+    },
     "@types/react": {
       "version": "16.9.56",
       "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.56.tgz",
@@ -3584,6 +3590,12 @@
         }
       }
     },
+    "base64-arraybuffer": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz",
+      "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==",
+      "optional": true
+    },
     "base64-js": {
       "version": "1.5.1",
       "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -3624,6 +3636,39 @@
       "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
       "optional": true
     },
+    "bl": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz",
+      "integrity": "sha1-/FQhoo/UImA2w7OJGmaiW8ZNIm4=",
+      "requires": {
+        "readable-stream": "~2.0.5"
+      },
+      "dependencies": {
+        "process-nextick-args": {
+          "version": "1.0.7",
+          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+          "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+        },
+        "readable-stream": {
+          "version": "2.0.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+          "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.1",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~1.0.6",
+            "string_decoder": "~0.10.x",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+        }
+      }
+    },
     "block-stream": {
       "version": "0.0.9",
       "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@@ -3702,6 +3747,14 @@
       "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
       "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
     },
+    "boom": {
+      "version": "2.10.1",
+      "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
+      "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
+      "requires": {
+        "hoek": "2.x.x"
+      }
+    },
     "bootstrap": {
       "version": "4.5.3",
       "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.3.tgz",
@@ -3838,6 +3891,11 @@
         "node-int64": "^0.4.0"
       }
     },
+    "btoa": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
+      "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g=="
+    },
     "buffer": {
       "version": "4.9.2",
       "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
@@ -4042,6 +4100,20 @@
       "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001165.tgz",
       "integrity": "sha512-8cEsSMwXfx7lWSUMA2s08z9dIgsnR5NAqjXP23stdsU3AUWkCr/rr4s4OFtHXn5XXr6+7kam3QFVoYyXNPdJPA=="
     },
+    "canvg": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.7.tgz",
+      "integrity": "sha512-4sq6iL5Q4VOXS3PL1BapiXIZItpxYyANVzsAKpTPS5oq4u3SKbGfUcbZh2gdLCQ3jWpG/y5wRkMlBBAJhXeiZA==",
+      "optional": true,
+      "requires": {
+        "@babel/runtime-corejs3": "^7.9.6",
+        "@types/raf": "^3.4.0",
+        "raf": "^3.4.1",
+        "rgbcolor": "^1.0.1",
+        "stackblur-canvas": "^2.0.0",
+        "svg-pathdata": "^5.0.5"
+      }
+    },
     "capture-exit": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",
@@ -4639,6 +4711,14 @@
         "which": "^1.2.9"
       }
     },
+    "cryptiles": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
+      "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
+      "requires": {
+        "boom": "2.x.x"
+      }
+    },
     "crypto-browserify": {
       "version": "3.12.0",
       "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
@@ -4720,6 +4800,15 @@
         }
       }
     },
+    "css-line-break": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-1.1.1.tgz",
+      "integrity": "sha512-1feNVaM4Fyzdj4mKPIQNL2n70MmuYzAXZ1aytlROFX1JsOo070OsugwGjj7nl6jnDJWHDM8zRZswkmeYVWZJQA==",
+      "optional": true,
+      "requires": {
+        "base64-arraybuffer": "^0.2.0"
+      }
+    },
     "css-loader": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-4.3.0.tgz",
@@ -5389,6 +5478,12 @@
         "domelementtype": "1"
       }
     },
+    "dompurify": {
+      "version": "2.2.6",
+      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.6.tgz",
+      "integrity": "sha512-7b7ZArhhH0SP6W2R9cqK6RjaU82FZ2UPM7RO8qN1b1wyvC/NY1FNWcX1Pu00fFOAnzEORtwXe4bPaClg6pUybQ==",
+      "optional": true
+    },
     "domutils": {
       "version": "1.7.0",
       "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
@@ -6630,6 +6725,70 @@
         }
       }
     },
+    "extract-zip": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.5.0.tgz",
+      "integrity": "sha1-ksz22B73Cp+kwXRxFMzvbYaIpsQ=",
+      "requires": {
+        "concat-stream": "1.5.0",
+        "debug": "0.7.4",
+        "mkdirp": "0.5.0",
+        "yauzl": "2.4.1"
+      },
+      "dependencies": {
+        "concat-stream": {
+          "version": "1.5.0",
+          "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.0.tgz",
+          "integrity": "sha1-U/fUPFHF5D+ByP3QMyHGMb5o1hE=",
+          "requires": {
+            "inherits": "~2.0.1",
+            "readable-stream": "~2.0.0",
+            "typedarray": "~0.0.5"
+          }
+        },
+        "debug": {
+          "version": "0.7.4",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz",
+          "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk="
+        },
+        "minimist": {
+          "version": "0.0.8",
+          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+        },
+        "mkdirp": {
+          "version": "0.5.0",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz",
+          "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=",
+          "requires": {
+            "minimist": "0.0.8"
+          }
+        },
+        "process-nextick-args": {
+          "version": "1.0.7",
+          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+          "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+        },
+        "readable-stream": {
+          "version": "2.0.6",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+          "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.1",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~1.0.6",
+            "string_decoder": "~0.10.x",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+        }
+      }
+    },
     "extsprintf": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
@@ -6687,6 +6846,14 @@
         "bser": "2.1.1"
       }
     },
+    "fd-slicer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
+      "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
+      "requires": {
+        "pend": "~1.2.0"
+      }
+    },
     "figgy-pudding": {
       "version": "3.5.2",
       "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
@@ -7112,6 +7279,22 @@
         "globule": "^1.0.0"
       }
     },
+    "generate-function": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
+      "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
+      "requires": {
+        "is-property": "^1.0.2"
+      }
+    },
+    "generate-object-property": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz",
+      "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=",
+      "requires": {
+        "is-property": "^1.0.0"
+      }
+    },
     "gensync": {
       "version": "1.0.0-beta.2",
       "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
@@ -7407,6 +7590,26 @@
         "minimalistic-assert": "^1.0.1"
       }
     },
+    "hasha": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz",
+      "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=",
+      "requires": {
+        "is-stream": "^1.0.1",
+        "pinkie-promise": "^2.0.0"
+      }
+    },
+    "hawk": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
+      "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
+      "requires": {
+        "boom": "2.x.x",
+        "cryptiles": "2.x.x",
+        "hoek": "2.x.x",
+        "sntp": "1.x.x"
+      }
+    },
     "he": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
@@ -7440,6 +7643,11 @@
         "minimalistic-crypto-utils": "^1.0.1"
       }
     },
+    "hoek": {
+      "version": "2.16.3",
+      "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
+      "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
+    },
     "hoist-non-react-statics": {
       "version": "3.3.2",
       "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
@@ -7561,6 +7769,15 @@
         }
       }
     },
+    "html2canvas": {
+      "version": "1.0.0-rc.7",
+      "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.0.0-rc.7.tgz",
+      "integrity": "sha512-yvPNZGejB2KOyKleZspjK/NruXVQuowu8NnV2HYG7gW7ytzl+umffbtUI62v2dCHQLDdsK6HIDtyJZ0W3neerA==",
+      "optional": true,
+      "requires": {
+        "css-line-break": "1.1.1"
+      }
+    },
     "htmlparser2": {
       "version": "3.10.1",
       "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
@@ -8177,6 +8394,23 @@
       "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
       "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE="
     },
+    "is-my-ip-valid": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz",
+      "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ=="
+    },
+    "is-my-json-valid": {
+      "version": "2.20.5",
+      "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.5.tgz",
+      "integrity": "sha512-VTPuvvGQtxvCeghwspQu1rBgjYUT6FGxPlvFKbYuFtgc4ADsX3U5ihZOYN0qyU6u+d4X9xXb0IT5O6QpXKt87A==",
+      "requires": {
+        "generate-function": "^2.0.0",
+        "generate-object-property": "^1.1.0",
+        "is-my-ip-valid": "^1.0.0",
+        "jsonpointer": "^4.0.0",
+        "xtend": "^4.0.0"
+      }
+    },
     "is-negative-zero": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
@@ -8231,6 +8465,11 @@
       "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz",
       "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c="
     },
+    "is-property": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
+      "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
+    },
     "is-regex": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
@@ -9847,6 +10086,30 @@
         }
       }
     },
+    "jsonpointer": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.1.0.tgz",
+      "integrity": "sha512-CXcRvMyTlnR53xMcKnuMzfCA5i/nfblTnnr74CZb6C4vG39eu6w51t7nKmU5MfLfbTgGItliNyjO/ciNPDqClg=="
+    },
+    "jspdf": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.2.0.tgz",
+      "integrity": "sha512-kz6blXdM+wQ0vWMDJsa7GW9Ya79DHQBWQL14urVsbr6mk9nsJCSqZuIgE1CPZ78i5Yih2uW4tqOTiLf5xSpT9Q==",
+      "requires": {
+        "atob": "^2.1.2",
+        "btoa": "^1.2.1",
+        "canvg": "^3.0.6",
+        "core-js": "^3.6.0",
+        "dompurify": "^2.2.0",
+        "html2canvas": "^1.0.0-rc.5",
+        "pako": "^1.0.11"
+      }
+    },
+    "jspdf-autotable": {
+      "version": "3.5.13",
+      "resolved": "https://registry.npmjs.org/jspdf-autotable/-/jspdf-autotable-3.5.13.tgz",
+      "integrity": "sha512-0oF5eHefuBjlKm60tNpPMmMS2oDNhY5U7vPkMh+s4/JZbnSjsmcUcP4j2r3k0sDvQz4ysmAi3MoOii9niJn7Og=="
+    },
     "jsprim": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -9946,6 +10209,11 @@
         "object.assign": "^4.1.1"
       }
     },
+    "kew": {
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz",
+      "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s="
+    },
     "killable": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@@ -9956,6 +10224,14 @@
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
       "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="
     },
+    "klaw": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+      "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
+      "requires": {
+        "graceful-fs": "^4.1.9"
+      }
+    },
     "kleur": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
@@ -10763,6 +11039,29 @@
         }
       }
     },
+    "node-phantom-simple": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/node-phantom-simple/-/node-phantom-simple-2.2.4.tgz",
+      "integrity": "sha1-T8Tv+7AvJB+1CCvU+6s5jkrstk0=",
+      "requires": {
+        "debug": "^2.2.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+        }
+      }
+    },
     "node-releases": {
       "version": "1.1.67",
       "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.67.tgz",
@@ -11348,11 +11647,202 @@
         "sha.js": "^2.4.8"
       }
     },
+    "pdf-maker": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/pdf-maker/-/pdf-maker-0.0.2.tgz",
+      "integrity": "sha1-3PNAtCaKBSMuhx+4cN9IvoW/5pw=",
+      "requires": {
+        "ejs": "^2.5.6",
+        "lodash": "^4.17.4",
+        "node-phantom-simple": "^2.2.4",
+        "phantomjs": "^2.1.7"
+      }
+    },
+    "pend": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+      "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
+    },
     "performance-now": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
     },
+    "phantomjs": {
+      "version": "2.1.7",
+      "resolved": "https://registry.npmjs.org/phantomjs/-/phantomjs-2.1.7.tgz",
+      "integrity": "sha1-xpEPZ5NcNyhbYRQyn8LyfV8+MTQ=",
+      "requires": {
+        "extract-zip": "~1.5.0",
+        "fs-extra": "~0.26.4",
+        "hasha": "^2.2.0",
+        "kew": "~0.7.0",
+        "progress": "~1.1.8",
+        "request": "~2.67.0",
+        "request-progress": "~2.0.1",
+        "which": "~1.2.2"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "2.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
+        },
+        "assert-plus": {
+          "version": "0.2.0",
+          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
+          "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ="
+        },
+        "aws-sign2": {
+          "version": "0.6.0",
+          "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
+          "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8="
+        },
+        "caseless": {
+          "version": "0.11.0",
+          "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
+          "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c="
+        },
+        "chalk": {
+          "version": "1.1.3",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+          "requires": {
+            "ansi-styles": "^2.2.1",
+            "escape-string-regexp": "^1.0.2",
+            "has-ansi": "^2.0.0",
+            "strip-ansi": "^3.0.0",
+            "supports-color": "^2.0.0"
+          }
+        },
+        "commander": {
+          "version": "2.20.3",
+          "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+          "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+        },
+        "form-data": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.1.tgz",
+          "integrity": "sha1-rjFduaSQf6BlUCMEpm13M0de43w=",
+          "requires": {
+            "async": "^2.0.1",
+            "combined-stream": "^1.0.5",
+            "mime-types": "^2.1.11"
+          }
+        },
+        "fs-extra": {
+          "version": "0.26.7",
+          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz",
+          "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=",
+          "requires": {
+            "graceful-fs": "^4.1.2",
+            "jsonfile": "^2.1.0",
+            "klaw": "^1.0.0",
+            "path-is-absolute": "^1.0.0",
+            "rimraf": "^2.2.8"
+          }
+        },
+        "har-validator": {
+          "version": "2.0.6",
+          "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
+          "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=",
+          "requires": {
+            "chalk": "^1.1.1",
+            "commander": "^2.9.0",
+            "is-my-json-valid": "^2.12.4",
+            "pinkie-promise": "^2.0.0"
+          }
+        },
+        "http-signature": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
+          "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
+          "requires": {
+            "assert-plus": "^0.2.0",
+            "jsprim": "^1.2.2",
+            "sshpk": "^1.7.0"
+          }
+        },
+        "jsonfile": {
+          "version": "2.4.0",
+          "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+          "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
+          "requires": {
+            "graceful-fs": "^4.1.6"
+          }
+        },
+        "node-uuid": {
+          "version": "1.4.8",
+          "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz",
+          "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc="
+        },
+        "oauth-sign": {
+          "version": "0.8.2",
+          "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
+          "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
+        },
+        "progress": {
+          "version": "1.1.8",
+          "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
+          "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74="
+        },
+        "qs": {
+          "version": "5.2.1",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.1.tgz",
+          "integrity": "sha1-gB/uAw4LlFDWOFrcSKTMVbRK7fw="
+        },
+        "request": {
+          "version": "2.67.0",
+          "resolved": "https://registry.npmjs.org/request/-/request-2.67.0.tgz",
+          "integrity": "sha1-ivdHgOK/EeoK6aqWXBHxGv0nJ0I=",
+          "requires": {
+            "aws-sign2": "~0.6.0",
+            "bl": "~1.0.0",
+            "caseless": "~0.11.0",
+            "combined-stream": "~1.0.5",
+            "extend": "~3.0.0",
+            "forever-agent": "~0.6.1",
+            "form-data": "~1.0.0-rc3",
+            "har-validator": "~2.0.2",
+            "hawk": "~3.1.0",
+            "http-signature": "~1.1.0",
+            "is-typedarray": "~1.0.0",
+            "isstream": "~0.1.2",
+            "json-stringify-safe": "~5.0.1",
+            "mime-types": "~2.1.7",
+            "node-uuid": "~1.4.7",
+            "oauth-sign": "~0.8.0",
+            "qs": "~5.2.0",
+            "stringstream": "~0.0.4",
+            "tough-cookie": "~2.2.0",
+            "tunnel-agent": "~0.4.1"
+          }
+        },
+        "supports-color": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
+        },
+        "tough-cookie": {
+          "version": "2.2.2",
+          "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz",
+          "integrity": "sha1-yDoYMPTl7wuT7yo0iOck+N4Basc="
+        },
+        "tunnel-agent": {
+          "version": "0.4.3",
+          "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
+          "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us="
+        },
+        "which": {
+          "version": "1.2.14",
+          "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
+          "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=",
+          "requires": {
+            "isexe": "^2.0.0"
+          }
+        }
+      }
+    },
     "picomatch": {
       "version": "2.2.2",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
@@ -13430,6 +13920,14 @@
         "uuid": "^3.3.2"
       }
     },
+    "request-progress": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz",
+      "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=",
+      "requires": {
+        "throttleit": "^1.0.0"
+      }
+    },
     "request-promise-core": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
@@ -13682,6 +14180,12 @@
       "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz",
       "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM="
     },
+    "rgbcolor": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
+      "integrity": "sha1-1lBezbMEplldom+ktDMHMGd1lF0=",
+      "optional": true
+    },
     "rimraf": {
       "version": "2.7.1",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
@@ -14457,6 +14961,14 @@
         }
       }
     },
+    "sntp": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
+      "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
+      "requires": {
+        "hoek": "2.x.x"
+      }
+    },
     "sockjs": {
       "version": "0.3.20",
       "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz",
@@ -14666,6 +15178,12 @@
         }
       }
     },
+    "stackblur-canvas": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.4.0.tgz",
+      "integrity": "sha512-Z+HixfgYV0ss3C342DxPwc+UvN1SYWqoz7Wsi3xEDWEnaBkSCL3Ey21gF4io+WlLm8/RIrSnCrDBIEcH4O+q5Q==",
+      "optional": true
+    },
     "stackframe": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz",
@@ -14839,6 +15357,11 @@
         }
       }
     },
+    "stringstream": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz",
+      "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA=="
+    },
     "strip-ansi": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
@@ -14947,6 +15470,12 @@
       "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz",
       "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ=="
     },
+    "svg-pathdata": {
+      "version": "5.0.5",
+      "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-5.0.5.tgz",
+      "integrity": "sha512-TAAvLNSE3fEhyl/Da19JWfMAdhSXTYeviXsLSoDT1UM76ADj5ndwAPX1FKQEgB/gFMPavOy6tOqfalXKUiXrow==",
+      "optional": true
+    },
     "svgo": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
@@ -15276,6 +15805,11 @@
       "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
       "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="
     },
+    "throttleit": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
+      "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw="
+    },
     "through2": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
@@ -17190,6 +17724,14 @@
         }
       }
     },
+    "yauzl": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
+      "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=",
+      "requires": {
+        "fd-slicer": "~1.0.1"
+      }
+    },
     "yocto-queue": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 59c5d4bf253d8b2cca002c5816636de13cf05cd5..6765f0af627be53b340e848008578da7d38ace22 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -14,9 +14,12 @@
     "@testing-library/user-event": "^12.5.0",
     "bootstrap": "^4.5.3",
     "dotenv": "^8.2.0",
+    "jspdf": "^2.2.0",
+    "jspdf-autotable": "^3.5.13",
     "moment": "^2.29.1",
     "node-sass": "^4.14.1",
     "notistack": "^1.0.2",
+    "pdf-maker": "0.0.2",
     "react": "^17.0.1",
     "react-bootstrap": "^1.4.0",
     "react-dom": "^17.0.1",
diff --git a/frontend/src/components/btmbuch/BuchungTabelle.js b/frontend/src/components/btmbuch/BuchungTabelle.js
index 6c38f7e9e97305604a459ac83e637a22706fd814..89c2e5acaadc52c4ddfbc4a0b95600503b9b9b3f 100644
--- a/frontend/src/components/btmbuch/BuchungTabelle.js
+++ b/frontend/src/components/btmbuch/BuchungTabelle.js
@@ -1,326 +1,382 @@
-import React, { useState, useEffect } from "react";
-import { faEdit, faTrash, faPlus } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { Table, Button, Row, Col } from "react-bootstrap";
-import { Collapse, Checkbox } from "@material-ui/core";
-import Moment from "react-moment";
-import { useSnackbar } from "notistack";
-import { useParams } from "react-router-dom";
-import TableBody from '@material-ui/core/TableBody';
-import NeueBuchungModal from "./NeueBuchungModal";
-import UpdateBuchungModal from "../../modals/UpdateBuchungModal";
-import DeleteModal from "../../modals/DeleteModal";
-import TablePagination from '@material-ui/core/TablePagination';
-
-function BuchungTabelle(props) {
-  let { btm } = props;
-  const { apoId } = useParams();
-
-  const [page, setPage] = React.useState(0);
-  const [rowsPerPage, setRowsPerPage] = React.useState(10);
-
-  const [open, setOpen] = useState(false);
-  const { enqueueSnackbar } = useSnackbar();
-
-  const [showNewBuchungModal, setShowNewBuchungModal] = useState(false);
-  const [showUpdateBuchungModal, setShowUpdateBuchungModal] = useState(false);
-  const [showDeleteModal, setShowDeleteModal] = useState(false);
-
-  const [lieferanten, setLieferanten] = useState([]);
-  const [aerzte, setAerzte] = useState([]);
-  const [empfaenger, setEmpfaenger] = useState([]);
-  const [selectedBuchung, setSelectedBuchung] = useState({});
-
-  const handleChangePage = (event, newPage) => {
-    setPage(newPage);
-  };
-
-  const handleChangeRowsPerPage = (event) => {
-    setRowsPerPage(+event.target.value);
-    setPage(0);
-  };
-
-  const loadLieferanten = () => {
-    fetch(`http://${process.env.REACT_APP_BACKEND_URL}/apotheke/${apoId}/lieferant`,
-      {
-        method: "GET",
-        headers: {
-          "Content-Type": "application/json",
-          Authorization:
-            "Bearer " + window.sessionStorage.getItem("edbapo-jwt"),
-        },
-      }
-    ).then(response => {
-      if (response.status === 200) {
-        setLieferanten(response.json());
-      } else if (response.status === 403) {
-        // props.history.push('/forbidden');
-      } else if (response.status === 400) {
-        // props.history.push('/badrequest');
-      }
-    }).catch((err) => {
-      //SHOW ERROR
-      console.log(err);
-    });
-
-
-  };
-
-  const loadAerzte = () => {
-    fetch(`http://${process.env.REACT_APP_BACKEND_URL}/apotheke/${apoId}/arzt`,
-      {
-        method: "GET",
-        headers: {
-          "Content-Type": "application/json",
-          Authorization:
-            "Bearer " + window.sessionStorage.getItem("edbapo-jwt"),
-        },
-      }
-    ).then(response => {
-      if (response.status === 200) {
-        setAerzte(response.json());
-      } else if (response.status === 403) {
-        // props.history.push('/forbidden');
-      } else if (response.status === 400) {
-        // props.history.push('/badrequest');
-      }
-    }).catch((err) => {
-      //SHOW ERROR
-      console.log(err);
-    });
-
-
-  };
-
-  const loadEmpfaenger = () => {
-    fetch(`http://${process.env.REACT_APP_BACKEND_URL}/apotheke/${apoId}/empfaenger`,
-      {
-        method: "GET",
-        headers: {
-          "Content-Type": "application/json",
-          Authorization:
-            "Bearer " + window.sessionStorage.getItem("edbapo-jwt"),
-        },
-      }
-    ).then(response => {
-      if (response.status === 200) {
-        setEmpfaenger(response.json());
-      } else if (response.status === 403) {
-        // props.history.push('/forbidden');
-      } else if (response.status === 400) {
-        // props.history.push('/badrequest');
-      }
-    }).catch((err) => {
-      //SHOW ERROR
-      console.log(err);
-    });
-
-
-  };
-
-  const deleteBtm = async () => {
-    const response = await fetch(
-      `http://${process.env.REACT_APP_BACKEND_URL}/apotheke/${apoId}/btmbuchung/${selectedBuchung.id}`,
-      {
-        method: "DELETE",
-        headers: {
-          Authorization:
-            "Bearer " + window.sessionStorage.getItem("edbapo-jwt"),
-        },
-      }
-    ).catch((err) => {
-      //SHOW ERROR
-      console.log(err);
-    });
-
-    if (response && response.status === 200) {
-      props.apothekeRefFunctions.updateBtmList();
-      enqueueSnackbar("Buchung erfolgreich gelöscht", {
-        variant: "success",
-        autoHideDuration: 3000,
-      });
-    } else {
-      //SHOW ERROR
-      console.log(response);
-    }
-  };
-
-  const update = (buchung) => {
-    setSelectedBuchung(buchung);
-    setShowUpdateBuchungModal(true);
-  };
-
-  const del = (buchung) => {
-    setSelectedBuchung(buchung);
-    setShowDeleteModal(true);
-  };
-
-  const renderEditButtons = (buchung) => {
-    return (
-      <Row style={{ display: "block" }}>
-        <Button onClick={() => update(buchung)} style={{ marginLeft: "0.5em" }}>
-          <FontAwesomeIcon icon={faEdit} />
-        </Button>
-        <Button onClick={() => del(buchung)} style={{ marginLeft: "0.5em" }}>
-          <FontAwesomeIcon icon={faTrash} />
-        </Button>
-      </Row>
-    );
-  };
-
-  const renderPruefButton = (buchung) => {
-    return (
-      <Row>
-        <Checkbox checked={buchung.pruefdatum} onChange={event => sendUpdateRequest(buchung)} style={{ marginLeft: "0.5em" }} ></Checkbox>
-      </Row>
-    );
-  };
-
-  const sendUpdateRequest = async (buchung) => {
-    let geprueft = buchung.pruefdatum == null;
-    const response = await fetch(`http://${process.env.REACT_APP_BACKEND_URL}/apotheke/${apoId}/btmbuchung/${buchung.id}?setGeprueft=${geprueft}`, {
-      method: "PUT",
-      headers: {
-        "Content-Type": "application/json",
-        Authorization: "Bearer " + window.sessionStorage.getItem("edbapo-jwt"),
-        body: JSON.stringify(buchung)
-      }
-    }).catch((err) => {
-      //SHOW ERROR
-      console.log(err);
-    });
-
-    if (response && response.status === 200) {
-      enqueueSnackbar('Buchung erfolgreich aktualisiert', { variant: 'success', autoHideDuration: 3000 });
-      props.apothekeRefFunctions.updateBtmList();
-    } else {
-      //SHOW ERROR
-      console.log(response);
-    }
-  };
-
-  useEffect(loadLieferanten, [apoId, props.history])
-  useEffect(loadAerzte, [apoId, props.history])
-  useEffect(loadEmpfaenger, [apoId, props.history])
-
-  return (
-    <React.Fragment>
-      <NeueBuchungModal
-        {...props}
-        lieferanten={lieferanten}
-        aerzte={aerzte}
-        empfaenger={empfaenger}
-        buchung={selectedBuchung}
-        show={showNewBuchungModal}
-        onHide={() => setShowNewBuchungModal(false)}
-      />
-      <UpdateBuchungModal
-        {...props}
-        lieferanten={lieferanten}
-        aerzte={aerzte}
-        empfaenger={empfaenger}
-        buchung={selectedBuchung}
-        show={showUpdateBuchungModal}
-        onHide={() => setShowUpdateBuchungModal(false)}
-      />
-
-      <DeleteModal
-        {...props}
-        headertext={"Betäubungsmittel-Buchung löschen"}
-        maintext={"Möchtest du diese Buchung wirklich löschen?"}
-        onSubmit={deleteBtm}
-        subtext={"Dieser Vorgang kann nicht rückgängig gemacht werden"}
-        show={showDeleteModal}
-        onHide={() => setShowDeleteModal(false)}
-      />
-
-      <div style={{ marginBottom: "2em" }}>
-        <Row
-          onClick={() => setOpen(!open)}
-          className="noselect btm-table-header-name"
-        >
-          <Col sm={3}>
-            <p>
-              {btm.btm.name} ({btm.btm.menge})
-						</p>
-          </Col>
-          <Col sm={9}>
-            <div style={{ marginLeft: "-9em" }}>
-              <Button
-                onClick={(event) => {
-                  event.stopPropagation();
-                  setShowNewBuchungModal(true);
-                }}
-              >
-                Neue Buchung
-								<FontAwesomeIcon
-                  style={{ marginLeft: "0.4em" }}
-                  icon={faPlus}
-                />
-              </Button>
-            </div>
-          </Col>
-        </Row>
-        <Collapse in={open}>
-          <Table striped bordered hover>
-            <thead>
-              <tr>
-                <th>Datum</th>
-                <th>Lieferant / Patient</th>
-                <th>Arztpraxis</th>
-                <th>Zugang</th>
-                <th>Abgang</th>
-                <th>Rezept Nr. / Lieferschein Nr.</th>
-                <th>Prüfdatum</th>
-                <th>Prüfer Kürzel</th>
-                {props.aktiveRolle.toLowerCase() === "admin" || props.aktiveRolle.toLowerCase() === "pruefer" ? (
-                  <th>Geprüft</th>
-                ) : null}
-                {props.aktiveRolle.toLowerCase() === "admin" ? (
-                  <th></th>
-                ) : null}
-              </tr>
-            </thead>
-            <TableBody>
-              {btm.buchungen.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((buchung) => (
-                <tr key={buchung.id}>
-                  <td> <Moment format="DD.MM.YYYY">{buchung.datum}</Moment> </td>
-                  <td>{buchung.typ === "ZUGANG"
-                    ? buchung.lieferant.name
-                    : buchung.empfaenger.vorname + " " + buchung.empfaenger.name}
-                  </td>
-                  <td>{buchung.typ === "ABGANG" ? buchung.arzt.name : ""}</td>
-                  <td>{buchung.typ === "ZUGANG" ? buchung.menge : ""}</td>
-                  <td>{buchung.typ === "ZUGANG" ? "" : buchung.menge}</td>
-                  <td>{buchung.typ === "ZUGANG" ? buchung.anforderungsschein : buchung.rezept}</td>
-                  <td>{buchung.pruefdatum ? <Moment format="DD.MM.YYYY">{buchung.pruefdatum}</Moment> : ""}</td>
-                  <td>{buchung.pruefer ? buchung.pruefer.vorname + " " + buchung.pruefer.name : ""}</td>
-
-                  {props.aktiveRolle.toLowerCase() === "admin" || props.aktiveRolle.toLowerCase() === "pruefer" ?
-                    <th>{renderPruefButton(buchung)}</th> : null}
-
-                  {props.aktiveRolle.toLowerCase() === "admin" ?
-                    <td style={{ textAlign: "center", verticalAlign: "middle" }} >
-                      {renderEditButtons(buchung)}
-                    </td> : null}
-
-                </tr>
-              ))}
-            </TableBody>
-          </Table>
-          <TablePagination
-            rowsPerPageOptions={[5, 10, 15]}
-            component="div"
-            count={btm.buchungen.length}
-            rowsPerPage={rowsPerPage}
-            page={page}
-            onChangePage={handleChangePage}
-            onChangeRowsPerPage={handleChangeRowsPerPage}
-          />
-        </Collapse>
-      </div>
-    </React.Fragment>
-  );
-}
-
-export default BuchungTabelle;
+import React, { useState, useEffect } from "react";
+import { faEdit, faTrash, faPlus } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { Table, Button, Row, Col } from "react-bootstrap";
+import { Collapse, Checkbox } from "@material-ui/core";
+import Moment from "react-moment";
+import { useSnackbar } from "notistack";
+import { useParams } from "react-router-dom";
+import TableBody from '@material-ui/core/TableBody';
+import NeueBuchungModal from "./NeueBuchungModal";
+import UpdateBuchungModal from "../../modals/UpdateBuchungModal";
+import DeleteModal from "../../modals/DeleteModal";
+import { makeStyles } from '@material-ui/core/styles';
+import TablePagination from '@material-ui/core/TablePagination';
+import jsPDF from 'jspdf'
+import 'jspdf-autotable'
+
+
+const useStyles = makeStyles({
+  root: {
+    width: '100%',
+  },
+  container: {
+    maxHeight: 440,
+  },
+});
+
+function BuchungTabelle(props) {
+  let { btm } = props;
+  const { apoId } = useParams();
+
+  const classes = useStyles();
+  const [page, setPage] = React.useState(0);
+  const [rowsPerPage, setRowsPerPage] = React.useState(10);
+
+  const [open, setOpen] = useState(false);
+  const { enqueueSnackbar } = useSnackbar();
+
+  const [showNewBuchungModal, setShowNewBuchungModal] = useState(false);
+  const [showUpdateBuchungModal, setShowUpdateBuchungModal] = useState(false);
+  const [showDeleteModal, setShowDeleteModal] = useState(false);
+
+  const [lieferanten, setLieferanten] = useState([]);
+  const [aerzte, setAerzte] = useState([]);
+  const [empfaenger, setEmpfaenger] = useState([]);
+  const [selectedBuchung, setSelectedBuchung] = useState({});
+
+  const handleChangePage = (event, newPage) => {
+    setPage(newPage);
+  };
+
+  const handleChangeRowsPerPage = (event) => {
+    setRowsPerPage(+event.target.value);
+    setPage(0);
+  };
+
+  const loadLieferanten = async () => {
+    const response = await fetch(
+      `http://${process.env.REACT_APP_BACKEND_URL}/apotheke/${props.apothekeId}/lieferant`,
+      {
+        method: "GET",
+        headers: {
+          "Content-Type": "application/json",
+          Authorization:
+            "Bearer " + window.sessionStorage.getItem("edbapo-jwt"),
+        },
+      }
+    ).catch((err) => {
+      //SHOW ERROR
+      console.log(err);
+    });
+
+    if (response.status === 200) {
+      setLieferanten(await response.json());
+    } else if (response.status === 403) {
+      // props.history.push('/forbidden');
+    } else if (response.status === 400) {
+      // props.history.push('/badrequest');
+    }
+  };
+
+  const loadAerzte = async () => {
+    const response = await fetch(
+      `http://${process.env.REACT_APP_BACKEND_URL}/apotheke/${props.apothekeId}/arzt`,
+      {
+        method: "GET",
+        headers: {
+          "Content-Type": "application/json",
+          Authorization:
+            "Bearer " + window.sessionStorage.getItem("edbapo-jwt"),
+        },
+      }
+    ).catch((err) => {
+      //SHOW ERROR
+      console.log(err);
+    });
+
+    if (response.status === 200) {
+      setAerzte(await response.json());
+    } else if (response.status === 403) {
+      // props.history.push('/forbidden');
+    } else if (response.status === 400) {
+      // props.history.push('/badrequest');
+    }
+  };
+
+  const loadEmpfaenger = async () => {
+    const response = await fetch(
+      `http://${process.env.REACT_APP_BACKEND_URL}/apotheke/${props.apothekeId}/empfaenger`,
+      {
+        method: "GET",
+        headers: {
+          "Content-Type": "application/json",
+          Authorization:
+            "Bearer " + window.sessionStorage.getItem("edbapo-jwt"),
+        },
+      }
+    ).catch((err) => {
+      //SHOW ERROR
+      console.log(err);
+    });
+
+    if (response.status === 200) {
+      setEmpfaenger(await response.json());
+    } else if (response.status === 403) {
+      // props.history.push('/forbidden');
+    } else if (response.status === 400) {
+      // props.history.push('/badrequest');
+    }
+  };
+
+  const deleteBtm = async () => {
+    const response = await fetch(
+      `http://${process.env.REACT_APP_BACKEND_URL}/apotheke/${apoId}/btmbuchung/${selectedBuchung.id}`,
+      {
+        method: "DELETE",
+        headers: {
+          Authorization:
+            "Bearer " + window.sessionStorage.getItem("edbapo-jwt"),
+        },
+      }
+    ).catch((err) => {
+      //SHOW ERROR
+      console.log(err);
+    });
+
+    if (response && response.status === 200) {
+      props.apothekeRefFunctions.updateBtmList();
+      enqueueSnackbar("Buchung erfolgreich gelöscht", {
+        variant: "success",
+        autoHideDuration: 3000,
+      });
+    } else {
+      //SHOW ERROR
+      console.log(response);
+    }
+  };
+
+  const update = (buchung) => {
+    setSelectedBuchung(buchung);
+    setShowUpdateBuchungModal(true);
+  };
+
+  const del = (buchung) => {
+    setSelectedBuchung(buchung);
+    setShowDeleteModal(true);
+  };
+
+  const renderEditButtons = (buchung) => {
+    return (
+      <Row style={{ display: "block" }}>
+        <Button onClick={() => update(buchung)} style={{ marginLeft: "0.5em" }}>
+          <FontAwesomeIcon icon={faEdit} />
+        </Button>
+        <Button onClick={() => del(buchung)} style={{ marginLeft: "0.5em" }}>
+          <FontAwesomeIcon icon={faTrash} />
+        </Button>
+      </Row>
+    );
+  };
+
+  const renderPruefButton = (buchung) => {
+    return (
+      <Row>
+        <Checkbox checked={buchung.pruefdatum} onChange={event => sendUpdateRequest(buchung)} style={{ marginLeft: "0.5em" }} ></Checkbox>
+      </Row>
+    );
+  };
+
+  const sendUpdateRequest = async (buchung) => {
+    let geprueft = buchung.pruefdatum == null;
+    const response = await fetch(`http://${process.env.REACT_APP_BACKEND_URL}/apotheke/${apoId}/btmbuchung/${buchung.id}?setGeprueft=${geprueft}`, {
+      method: "PUT",
+      headers: {
+        "Content-Type": "application/json",
+        Authorization: "Bearer " + window.sessionStorage.getItem("edbapo-jwt"),
+        body: JSON.stringify(buchung)
+      }
+    }).catch((err) => {
+      //SHOW ERROR
+      console.log(err);
+    });
+
+    if (response && response.status === 200) {
+      enqueueSnackbar('Buchung erfolgreich aktualisiert', { variant: 'success', autoHideDuration: 3000 });
+      props.apothekeRefFunctions.updateBtmList();
+    } else {
+      //SHOW ERROR
+      console.log(response);
+    }
+  };
+
+  const exportPdf = () => {
+    const unit = "pt";
+    const size = "A4"; // Use A1, A2, A3 or A4
+    const orientation = "portrait"; // portrait or landscape
+
+    const marginLeft = 40;
+    const doc = new jsPDF(orientation, unit, size);
+
+    doc.setFontSize(10);
+    console.log('print btm liste', btm.name);
+
+    const title = [props.btm.btm.name];
+    const headers = [["Datum", "Lieferant/Patient","Arztpraxis", "Zugang", "Abgang", "Rp.Nr./L.Nr.", "Prüfdatum", "Prüfer Kürzel"]];
+
+    const moment = require('moment');
+ 
+    const data = btm.buchungen.map(buchung => [moment(buchung.datum).format("DD.MM.YYYY"),
+    buchung.typ === "ZUGANG" ? buchung.lieferant.name : buchung.empfaenger.vorname + " " + buchung.empfaenger.name,
+    buchung.typ === "ABGANG" ? buchung.arzt.name : "",
+    buchung.typ === "ZUGANG" ? buchung.menge : "",
+    buchung.typ === "ZUGANG" ? "" : buchung.menge,
+    buchung.typ === "ZUGANG" ? buchung.anforderungsschein : buchung.rezept,
+    buchung.pruefdatum ? moment(buchung.pruefdatum).format("DD.MM.YYYY") : "",
+    buchung.pruefer ? buchung.pruefer.vorname+" "+buchung.pruefer.name : "",
+   ]);
+ 
+    let content = {
+      startY: 50,
+      head: headers,
+      body: data
+    };
+  
+
+ 
+    doc.text(title, marginLeft, 40);
+    doc.autoTable(content);
+    doc.save("BtmListe.pdf")
+
+  }
+
+  useEffect(() => {
+    loadLieferanten();
+    loadAerzte();
+    loadEmpfaenger();
+  }, []);
+
+  return (
+    <React.Fragment>
+      <NeueBuchungModal
+        {...props}
+        lieferanten={lieferanten}
+        aerzte={aerzte}
+        empfaenger={empfaenger}
+        buchung={selectedBuchung}
+        show={showNewBuchungModal}
+        onHide={() => setShowNewBuchungModal(false)}
+      />
+      <UpdateBuchungModal
+        {...props}
+        lieferanten={lieferanten}
+        aerzte={aerzte}
+        empfaenger={empfaenger}
+        buchung={selectedBuchung}
+        show={showUpdateBuchungModal}
+        onHide={() => setShowUpdateBuchungModal(false)}
+      />
+
+      <DeleteModal
+        {...props}
+        headertext={"Betäubungsmittel-Buchung löschen"}
+        maintext={"Möchtest du diese Buchung wirklich löschen?"}
+        onSubmit={deleteBtm}
+        subtext={"Dieser Vorgang kann nicht rückgängig gemacht werden"}
+        show={showDeleteModal}
+        onHide={() => setShowDeleteModal(false)}
+      />
+
+      <div style={{ marginBottom: "2em" }}>
+        <Row
+          onClick={() => setOpen(!open)}
+          className="noselect btm-table-header-name"
+        >
+          <Col sm={3}>
+            <p>
+              {btm.btm.name} ({btm.btm.menge})
+						</p>
+          </Col>
+          <Col sm={9}>
+            <div style={{ marginLeft: "-9em" }}>
+            <Button style={{ marginRight: "1em" }} onClick={exportPdf}>
+                PDF
+              </Button>
+              <Button
+                onClick={(event) => {
+                  event.stopPropagation();
+                  setShowNewBuchungModal(true);
+                }}
+              >
+                Neue Buchung
+								<FontAwesomeIcon
+                  style={{ marginLeft: "0.4em" }}
+                  icon={faPlus}
+                />
+              </Button>
+            </div>
+          </Col>
+        </Row>
+        <Collapse in={open}>
+          <Table striped bordered hover id="btm-table">
+            <thead>
+              <tr>
+                <th>Datum</th>
+                <th>Lieferant / Patient</th>
+                <th>Arztpraxis</th>
+                <th>Zugang</th>
+                <th>Abgang</th>
+                <th>Rezept Nr. / Lieferschein Nr.</th>
+                <th>Prüfdatum</th>
+                <th>Prüfer Kürzel</th>
+                {props.aktiveRolle.toLowerCase() === "admin" || props.aktiveRolle.toLowerCase() === "pruefer" ? (
+                  <th>Geprüft</th>
+                ) : null}
+                {props.aktiveRolle.toLowerCase() === "admin" ? (
+                  <th></th>
+                ) : null}
+              </tr>
+            </thead>
+            <TableBody>
+              {btm.buchungen.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((buchung) => (
+                <tr key={buchung.id}>
+                  <td> <Moment format="DD.MM.YYYY">{buchung.datum}</Moment> </td>
+                  <td>{buchung.typ === "ZUGANG"
+                    ? buchung.lieferant.name
+                    : buchung.empfaenger.vorname + " " + buchung.empfaenger.name}
+                  </td>
+                  <td>{buchung.typ === "ABGANG" ? buchung.arzt.name : ""}</td>
+                  <td>{buchung.typ === "ZUGANG" ? buchung.menge : ""}</td>
+                  <td>{buchung.typ === "ZUGANG" ? "" : buchung.menge}</td>
+                  <td>{buchung.typ === "ZUGANG" ? buchung.anforderungsschein : buchung.rezept}</td>
+                  <td>{buchung.pruefdatum ? <Moment format="DD.MM.YYYY">{buchung.pruefdatum}</Moment> : ""}</td>
+                  <td>{buchung.pruefer ? buchung.pruefer.vorname+" "+buchung.pruefer.name : ""}</td>
+
+                  {props.aktiveRolle.toLowerCase() === "admin" || props.aktiveRolle.toLowerCase() === "pruefer" ?
+                    <th>{renderPruefButton(buchung)}</th> : null}
+
+                  {props.aktiveRolle.toLowerCase() === "admin" ?
+                    <td style={{ textAlign: "center", verticalAlign: "middle" }} >
+                      {renderEditButtons(buchung)}
+                    </td> : null}
+
+                </tr>
+              ))}
+            </TableBody>
+          </Table>
+          <TablePagination
+            rowsPerPageOptions={[5, 10, 15]}
+            component="div"
+            count={btm.buchungen.length}
+            rowsPerPage={rowsPerPage}
+            page={page}
+            onChangePage={handleChangePage}
+            onChangeRowsPerPage={handleChangeRowsPerPage}
+          />
+        </Collapse>
+      </div>
+    </React.Fragment>
+  );
+}
+
+export default BuchungTabelle;