diff --git a/task_2_ts/.prettierrc.json b/task_2_ts/.prettierrc.json
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/task_2_ts/.prettierrc.json
@@ -0,0 +1 @@
+{}
diff --git a/task_2_ts/Dockerfile b/task_2_ts/Dockerfile
new file mode 100644
index 0000000..b60efdc
--- /dev/null
+++ b/task_2_ts/Dockerfile
@@ -0,0 +1,8 @@
+FROM node
+WORKDIR /app
+COPY package.json .
+RUN npm i
+COPY . .
+## EXPOSE [Port you mentioned in the vite.config file]
+EXPOSE 5173
+CMD ["npm", "run", "dev"]
\ No newline at end of file
diff --git a/task_2_ts/css/layout.css b/task_2_ts/css/layout.css
new file mode 100644
index 0000000..480745a
--- /dev/null
+++ b/task_2_ts/css/layout.css
@@ -0,0 +1,115 @@
+:root {
+ --spacing: 0.25rem;
+ --border-color: #a0a0a0;
+}
+
+/* Style for definition list */
+dl {
+ margin-top: 0;
+ margin-bottom: 20px;
+}
+
+dt,
+dd {
+ line-height: 1.42857143;
+}
+
+dt {
+ font-weight: 700;
+}
+
+dd {
+ margin-left: 0;
+}
+
+body h1,
+body h2 {
+ margin-bottom: 0;
+}
+
+nav {
+ border-bottom: 1px solid var(--border-color);
+}
+
+article {
+ width: 400px;
+}
+
+body>main {
+ max-height: calc(100vh - 100px);
+ overflow-y: auto;
+
+ padding: var(--spacing) !important;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: start;
+ gap: var(--spacing);
+
+ & article {
+ margin: 0;
+ padding: var(--spacing);
+
+ &>header {
+ margin: calc(var(--spacing) * -1) calc(var(--spacing) * -1) var(--spacing);
+ padding: var(--spacing);
+ }
+ }
+}
+
+/* Set a fixed scrollable wrapper */
+#table-content {
+ max-height: 400px;
+ overflow: auto;
+
+ /* Set header to stick to the top of the container. */
+ & thead tr th {
+ position: sticky;
+ top: 0;
+ }
+
+ /* If we use border, we must use table-collapse to avoid a slight movement of the header row */
+ & table {
+ border-collapse: collapse;
+ border-top: 0;
+ }
+
+ /* Because we must set sticky on th, we have to apply background styles here rather than on thead */
+ & th {
+ border-left: 1px dotted rgba(200, 209, 224, 0.6);
+ border-bottom: 1px solid #ddd;
+
+ background: #eee;
+ text-align: left;
+ box-shadow: 0px 0px 0 2px #e8e8e8;
+
+ &.active {
+ background: #ddd;
+ }
+
+ &.sortable::after {
+ font-family: FontAwesome;
+ content: "\f0dc";
+ position: absolute;
+ right: 8px;
+ color: #999;
+ }
+
+ &.active::after {
+ position: absolute;
+ right: 8px;
+ color: #999;
+ }
+
+ &.active.asc::after {
+ font-family: FontAwesome;
+ content: "\f0d8";
+ }
+
+ &.active.desc::after {
+ font-family: FontAwesome;
+ content: "\f0d7";
+ }
+ }
+}
diff --git a/task_2_ts/index.html b/task_2_ts/index.html
new file mode 100644
index 0000000..e0aaf4f
--- /dev/null
+++ b/task_2_ts/index.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+ Open data explorer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Selected column infos
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/task_2_ts/package.json b/task_2_ts/package.json
new file mode 100644
index 0000000..e67d2e7
--- /dev/null
+++ b/task_2_ts/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "vite-typescript-starter",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "format": "prettier . --write",
+ "tsc": "tsc"
+ },
+ "devDependencies": {
+ "prettier": "^3.0.1",
+ "typescript": "^5.1.6",
+ "vite": "^4.4.9"
+ },
+ "dependencies": {
+ "@fortawesome/fontawesome-free": "^6.4.2",
+ "@picocss/pico": "^1.5.10",
+ "json-2-csv": "^4.1.0"
+ }
+}
diff --git a/task_2_ts/ts/csv.ts b/task_2_ts/ts/csv.ts
new file mode 100644
index 0000000..d45100e
--- /dev/null
+++ b/task_2_ts/ts/csv.ts
@@ -0,0 +1,30 @@
+import {
+ csv2json
+} from 'json-2-csv';
+
+export type CSV_Data = Array>;
+
+const convertCSVtoJSON = async ( csvText: string ) => {
+ // Type cast OK, as the typing of the external library is not perfect.
+ return ( await csv2json( csvText ) ) as CSV_Data;
+};
+
+/**
+ * Reads a CSV file and returns the data as JSON.
+ * @param event The change event of the file input.
+ */
+export const readCSV = async ( event: Event ): Promise => {
+ if ( !( event.target instanceof HTMLInputElement ) ) {
+ throw new Error( 'Not an HTMLInputElement' );
+ }
+
+ const file = event.target.files?.[0];
+
+ if ( file == null ) {
+ throw new Error( 'No file selected' );
+ }
+
+ const result = await file.text();
+
+ return await convertCSVtoJSON( result );
+};
diff --git a/task_2_ts/ts/main.ts b/task_2_ts/ts/main.ts
new file mode 100644
index 0000000..1bb0220
--- /dev/null
+++ b/task_2_ts/ts/main.ts
@@ -0,0 +1,5 @@
+import "@fortawesome/fontawesome-free/css/all.css";
+import "../css/layout.css";
+import "@picocss/pico/css/pico.min.css";
+
+// TODO start here with the first entry point
diff --git a/task_2_ts/tsconfig.json b/task_2_ts/tsconfig.json
new file mode 100644
index 0000000..b7fbeec
--- /dev/null
+++ b/task_2_ts/tsconfig.json
@@ -0,0 +1,33 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+
+ "strict": true,
+ "allowUnusedLabels": false,
+ "allowUnreachableCode": false,
+ "exactOptionalPropertyTypes": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitOverride": true,
+ "noImplicitReturns": true,
+ "noPropertyAccessFromIndexSignature": true,
+ "noUncheckedIndexedAccess": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "allowJs": false,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "include": ["**/*"],
+ "exclude": ["tests/**/*", "public/**/*", "build/**/*"]
+}
diff --git a/task_2_ts/vite-env.d.ts b/task_2_ts/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/task_2_ts/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/task_2_ts/vite.config.js b/task_2_ts/vite.config.js
new file mode 100644
index 0000000..4967025
--- /dev/null
+++ b/task_2_ts/vite.config.js
@@ -0,0 +1,7 @@
+export default {
+ server: {
+ host: '0.0.0.0',
+ port: 5173,
+ allowedHosts: true,
+ },
+}
\ No newline at end of file