diff --git a/application/controllers/Studentenverwaltung.php b/application/controllers/Studentenverwaltung.php
new file mode 100644
index 000000000..dded0ffdd
--- /dev/null
+++ b/application/controllers/Studentenverwaltung.php
@@ -0,0 +1,19 @@
+load->view('Studentenverwaltung');
+ }
+}
diff --git a/application/controllers/components/Studentenverwaltung.php b/application/controllers/components/Studentenverwaltung.php
new file mode 100644
index 000000000..d03c7e350
--- /dev/null
+++ b/application/controllers/components/Studentenverwaltung.php
@@ -0,0 +1,60 @@
+load->model('organisation/Studiengang_model', 'StudiengangModel');
+ $result = $this->StudiengangModel->loadWhere(['aktiv' => true]);
+ if (isError($result))
+ return $this->outputJson($result);
+ if (!hasData($result))
+ return $this->outputJsonSuccess([]);
+ $list = getData($result);
+ $list[] = [
+ 'name' => 'International',
+ 'children' => [
+ [
+ 'name' => 'Incoming',
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Outgoing',
+ 'leaf' => true
+ ],
+ [
+ 'name' => 'Gemeinsame Studien',
+ 'leaf' => true
+ ]
+ ]
+ ];
+ $this->outputJsonSuccess($list);
+ }
+
+ /**
+ * @param integer $studiengang_kz
+ * @return void
+ */
+ public function getStudiengang($studiengang_kz)
+ {
+ // TODO(chris): load stgSemester + prestudent
+ $this->outputJson([
+ [
+ 'key' => 2,
+ 'name' => 'PreStudent'
+ ]
+ ]);
+ }
+}
diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php
new file mode 100644
index 000000000..20a89f8e8
--- /dev/null
+++ b/application/views/Studentenverwaltung.php
@@ -0,0 +1,53 @@
+ 'Studentenverwaltung',
+ 'axios027' => true,
+ 'bootstrap5' => true,
+ 'fontawesome6' => true,
+ 'vue3' => true,
+ 'primevue3' => true,
+ 'filtercomponent' => true,
+ 'tabulator5' => true,
+ 'phrases' => [],
+ 'customCSSs' => [
+ 'public/css/Studentenverwaltung.css'
+ ],
+ 'customJSModules' => [
+ 'public/js/apps/Studentenverwaltung.js'
+ ]
+ );
+
+ $this->load->view('templates/FHC-Header', $includesArray);
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+load->view('templates/FHC-Footer', $includesArray); ?>
+
diff --git a/public/css/Studentenverwaltung.css b/public/css/Studentenverwaltung.css
new file mode 100644
index 000000000..ccc5b0694
--- /dev/null
+++ b/public/css/Studentenverwaltung.css
@@ -0,0 +1,60 @@
+@import './components/searchbar.css';
+@import './components/verticalsplit.css';
+
+.searchbar {
+ margin-right: 0!important;
+}
+.searchbar > .input-group {
+ margin-right: 0!important;
+}
+.searchbar > .input-group > * {
+ border-radius: 0!important;
+}
+
+#main {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+}
+#main > header {
+ flex: 0 0 auto;
+}
+#main > div {
+ flex: 1 1 auto;
+}
+
+@media (min-width: 768px) {
+ #sidebarMenu {
+ visibility: visible!important;
+ transform: none;
+ position: inherit;
+ z-index: 1;
+ }
+}
+
+
+@media (max-width: 769px) {
+ .stv-verband {
+ max-height: calc(100% - 3rem);
+ overflow: auto;
+ }
+}
+.stv-verband .p-treetable-tbody > tr > td {
+ display: flex;
+ padding-top: .25rem!important;
+ padding-bottom: .25rem!important;
+}
+.stv-verband .p-treetable-tbody > tr > td > button {
+ flex: 0 0 auto;
+}
+.stv-verband .p-treetable-tbody > tr > td > span {
+ flex: 1 1 auto;
+}
+
+.stv-list {
+ display: flex;
+ flex-direction: column;
+}
+.stv-list > #filterTableDataset {
+ flex: 1 1 auto;
+}
\ No newline at end of file
diff --git a/public/js/apps/Studentenverwaltung.js b/public/js/apps/Studentenverwaltung.js
new file mode 100644
index 000000000..bdec5d033
--- /dev/null
+++ b/public/js/apps/Studentenverwaltung.js
@@ -0,0 +1,88 @@
+/**
+ * Copyright (C) 2022 fhcomplete.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+import FhcSearchbar from "../components/searchbar/searchbar.js";
+import StvVerband from "../components/Studienverwaltung/Verband.js";
+import StvList from "../components/Studienverwaltung/List.js";
+import StvStudent from "../components/Studienverwaltung/Student.js";
+import VerticalSplit from "../components/verticalsplit/verticalsplit.js";
+import fhcapifactory from "./api/fhcapifactory.js";
+
+Vue.$fhcapi = fhcapifactory;
+
+const app = Vue.createApp({
+ components: {
+ FhcSearchbar,
+ StvVerband,
+ StvList,
+ StvStudent,
+ VerticalSplit
+ },
+ data() {
+ return {
+ selected: [],
+ searchbaroptions: {
+ types: [
+ "person",
+ "student",
+ "prestudent"
+ ],
+ actions: {
+ person: {
+ defaultaction: {
+ type: "link",
+ action: function(data) {
+ return data.profil;
+ }
+ },
+ childactions: [
+ {
+ "label": "testchildaction1",
+ "icon": "fas fa-check-circle",
+ "type": "function",
+ "action": function(data) {
+ alert('person testchildaction 01 ' + JSON.stringify(data));
+ }
+ },
+ {
+ "label": "testchildaction2",
+ "icon": "fas fa-file-csv",
+ "type": "function",
+ "action": function(data) {
+ alert('person testchildaction 02 ' + JSON.stringify(data));
+ }
+ }
+ ]
+ }
+ }
+ },
+ }
+ },
+ computed: {
+ lastSelected() {
+ return this.selected[this.selected.length - 1];
+ }
+ },
+ methods: {
+ searchfunction(searchsettings) {
+ return Vue.$fhcapi.Search.search(searchsettings);
+ }
+ }
+});
+
+app.use(primevue.config.default).mount('#main');
+
diff --git a/public/js/components/Studienverwaltung/Details.js b/public/js/components/Studienverwaltung/Details.js
new file mode 100644
index 000000000..f119b34e4
--- /dev/null
+++ b/public/js/components/Studienverwaltung/Details.js
@@ -0,0 +1,9 @@
+export default {
+ props: {
+ student: Object
+ },
+ template: `
+
+ {{student}}
+
`
+};
\ No newline at end of file
diff --git a/public/js/components/Studienverwaltung/List.js b/public/js/components/Studienverwaltung/List.js
new file mode 100644
index 000000000..9a32914b7
--- /dev/null
+++ b/public/js/components/Studienverwaltung/List.js
@@ -0,0 +1,69 @@
+import {CoreFilterCmpt} from "../filter/Filter.js";
+
+export default {
+ components: {
+ CoreFilterCmpt
+ },
+ props: {
+ selected: Array
+ },
+ emits: [
+ 'update:selected'
+ ],
+ data() {
+ return {
+ tabulatorOptions: {
+ columns:[ //Define Table Columns
+ {title:"Name", field:"name", width:150},
+ {title:"Age", field:"age", hozAlign:"left", formatter:"progress"},
+ {title:"Favourite Color", field:"col"},
+ {title:"Date Of Birth", field:"dob", sorter:"date", hozAlign:"center"},
+ ],
+ data: [
+ {id:1, name:"Oli Bob", age:"12", col:"red", dob:""},
+ {id:2, name:"Mary May", age:"1", col:"blue", dob:"14/05/1982"},
+ {id:3, name:"Christine Lobowski", age:"42", col:"green", dob:"22/05/1982"},
+ {id:4, name:"Brendon Philips", age:"125", col:"orange", dob:"01/08/1980"},
+ {id:5, name:"Margret Marmajuke", age:"16", col:"yellow", dob:"31/01/1999"},
+ {id:6, name:"Oli Bob", age:"12", col:"red", dob:""},
+ {id:7, name:"Mary May", age:"1", col:"blue", dob:"14/05/1982"},
+ {id:8, name:"Christine Lobowski", age:"42", col:"green", dob:"22/05/1982"},
+ {id:9, name:"Brendon Philips", age:"125", col:"orange", dob:"01/08/1980"}
+ ],
+
+ height: 'auto',
+ selectable: true
+ },
+ tabulatorEvents: [
+ {
+ event: 'rowSelectionChanged',
+ handler: this.rowSelectionChanged
+ }
+ ]
+ }
+ },
+ methods: {
+ actionNewPrestudent() {
+ console.log('actionNewPrestudent');
+ },
+ rowSelectionChanged(data) {
+ this.$emit('update:selected', data);
+ }
+ },
+ mounted() {
+ },
+ template: `
+
+
+
+
`
+};
\ No newline at end of file
diff --git a/public/js/components/Studienverwaltung/Verband.js b/public/js/components/Studienverwaltung/Verband.js
new file mode 100644
index 000000000..e7abbbcd4
--- /dev/null
+++ b/public/js/components/Studienverwaltung/Verband.js
@@ -0,0 +1,68 @@
+import {CoreRESTClient} from '../../RESTClient.js';
+
+export default {
+ components: {
+ TreeTable: primevue.treetable,
+ TreeColumn: primevue.column
+ },
+ data() {
+ return {
+ loading: true,
+ nodes: []
+ }
+ },
+ methods: {
+ onExpandTreeNode(node) {
+ if (!node.children) {
+ let url = '';
+ if (node.data.studiengang_kz) {
+ url = "getStudiengang/" + node.data.studiengang_kz;
+ }
+
+ if (url) {
+ this.loading = true;
+ CoreRESTClient
+ .get("components/Studentenverwaltung/" + url)
+ .then(result => {
+ const subNodes = result.data.map(this.mapResultToTreeData);
+ node.children = subNodes;
+ this.loading = false;
+ });
+ }
+ }
+ },
+ mapResultToTreeData(el) {
+ const cp = {
+ data: el
+ };
+ if (el.studiengang_kz !== undefined) {
+ // TODO(chris): scrolling doesn't work
+ cp.key = el.studiengang_kz;
+ cp.data.name = el.bezeichnung;
+ cp.leaf = false;
+ }
+ if (el.children)
+ cp.children = el.children.map(this.mapResultToTreeData);
+ else
+ cp.leaf = el.leaf || false;
+ return cp;
+ }
+ },
+ mounted() {
+ CoreRESTClient
+ .get("components/Studentenverwaltung")
+ .then(result => result.data)
+ .then(result => {
+ if(CoreRESTClient.isError(result)) {
+ console.error(CoreRESTClient.getError(result));
+ } else if (CoreRESTClient.hasData(result)) {
+ this.nodes = CoreRESTClient.getData(result).map(this.mapResultToTreeData);
+ }
+ this.loading = false;
+ });
+ },
+ template: `
+
+
+ `
+};
\ No newline at end of file