diff --git a/application/controllers/Cis/Zeitsperren.php b/application/controllers/Cis/Zeitsperren.php
new file mode 100644
index 000000000..e337b2f98
--- /dev/null
+++ b/application/controllers/Cis/Zeitsperren.php
@@ -0,0 +1,30 @@
+ ['basis/cis:r'],
+ ]);
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ }
+
+ /**
+ * index loads the view Zeitsperren
+ * @access public
+ * @return void
+ */
+ public function index()
+ {
+ $viewData = array(
+ 'uid'=>getAuthUID(),
+ );
+
+ $this->load->view('CisRouterView/CisRouterView.php',['viewData' => $viewData, 'route' => 'zeitsperren']);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/Zeitsperren.php b/application/controllers/api/frontend/v1/Zeitsperren.php
new file mode 100644
index 000000000..96a76da31
--- /dev/null
+++ b/application/controllers/api/frontend/v1/Zeitsperren.php
@@ -0,0 +1,49 @@
+ self::PERM_LOGGED,
+ 'getTypenZeitsperren' => self::PERM_LOGGED,
+ ]);
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ $this->load->library('form_validation');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'ui',
+ 'person'
+ ]);
+
+ // Load models
+ $this->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
+ $this->load->model('ressource/Zeitsperretyp_model', 'ZeitsperretypModel');
+ }
+
+ public function getZeitsperrenUser($uid)
+ {
+ $result = $this->ZeitsperreModel->getZeitsperrenUser($uid);
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ public function getTypenZeitsperren()
+ {
+ $this->ZeitsperretypModel->addOrder('beschreibung', 'ASC');
+ $result = $this->ZeitsperretypModel->load();
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+}
diff --git a/application/models/ressource/Zeitsperre_model.php b/application/models/ressource/Zeitsperre_model.php
index 078d29d8b..25eee4b9a 100644
--- a/application/models/ressource/Zeitsperre_model.php
+++ b/application/models/ressource/Zeitsperre_model.php
@@ -61,4 +61,39 @@ class Zeitsperre_model extends DB_Model
return $this->execQuery($qry);
}
+
+ /**
+ * get Zeitsperren of a user
+ *
+ * @param $uid mitarbeiteruid
+ * @return array
+ */
+ public function getZeitsperrenUser($uid, $bisgrenze=true)
+ {
+ //TODO(Manu) check if bisDate is needed
+/* $parametersArray = array();
+ array_push($parametersArray, $uid);
+ $parametersArray = [$uid];*/
+
+ $qry = "
+ SELECT tbl_zeitsperre.*, tbl_zeitsperretyp.*, tbl_erreichbarkeit.farbe AS erreichbarkeit_farbe, tbl_erreichbarkeit.beschreibung AS erreichbarkeit_beschreibung
+ FROM (campus.tbl_zeitsperre JOIN campus.tbl_zeitsperretyp USING (zeitsperretyp_kurzbz))
+ LEFT JOIN campus.tbl_erreichbarkeit USING (erreichbarkeit_kurzbz)
+ WHERE mitarbeiter_uid= ?
+ ";
+
+ if($bisgrenze)
+ {
+ $qry.="
+ AND (
+ (date_part('month',vondatum)>=9 AND date_part('year', vondatum)>='".(date('Y')-1)."')
+ OR
+ (date_part('month',vondatum)<9 AND date_part('year', vondatum)>='".(date('Y'))."')
+ )";
+ }
+
+ $qry.= " ORDER BY vondatum DESC";
+
+ return $this->execQuery($qry, array('mitarbeiter_uid' => $uid));
+ }
}
diff --git a/public/js/api/factory/cis/zeitsperren.js b/public/js/api/factory/cis/zeitsperren.js
new file mode 100644
index 000000000..bb8d4d891
--- /dev/null
+++ b/public/js/api/factory/cis/zeitsperren.js
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2026 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 .
+ */
+
+export default {
+ getTimelocksUser(uid) {
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/Zeitsperren/getZeitsperrenUser/' + uid
+ };
+ },
+ getTypenZeitsperren(){
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/Zeitsperren/getTypenZeitsperren/'
+ };
+ }
+};
\ No newline at end of file
diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js
index 190ed1a93..540d9619a 100644
--- a/public/js/apps/Dashboard/Fhc.js
+++ b/public/js/apps/Dashboard/Fhc.js
@@ -16,6 +16,7 @@ import AbgabetoolStudent from "../../components/Cis/Abgabetool/AbgabetoolStudent
import AbgabetoolMitarbeiter from "../../components/Cis/Abgabetool/AbgabetoolMitarbeiter.js";
import DeadlineOverview from "../../components/Cis/Abgabetool/DeadlineOverview.js";
import Studium from "../../components/Cis/Studium/Studium.js";
+import Zeitsperren from "../../components/Cis/Zeitsperren/Zeitsperren.js";
import ApiRenderers from '../../api/factory/renderers.js';
import ApiRouteInfo from '../../api/factory/routeinfo.js';
@@ -216,6 +217,12 @@ const router = VueRouter.createRouter({
};
},
},
+ {
+ path: `/Cis/Zeitsperren`,
+ name: 'Zeitsperren',
+ component: Zeitsperren,
+ props: true
+ },
]
})
diff --git a/public/js/components/Cis/Zeitsperren/Zeitsperren.js b/public/js/components/Cis/Zeitsperren/Zeitsperren.js
new file mode 100644
index 000000000..e779bdbf6
--- /dev/null
+++ b/public/js/components/Cis/Zeitsperren/Zeitsperren.js
@@ -0,0 +1,272 @@
+import {CoreFilterCmpt} from "../../filter/Filter.js";
+import FormForm from '../../Form/Form.js';
+import FormInput from '../../Form/Input.js';
+
+import ApiAuthinfo from '../../../api/factory/authinfo.js';
+import ApiTimelocks from "../../../api/factory/cis/zeitsperren.js";
+
+export default {
+ name: 'ZeitsperrenComponent',
+ components: {
+ CoreFilterCmpt,
+ FormForm,
+ FormInput
+ },
+ data(){
+ return {
+ uid: null,
+ listTypenZeitsperren: [],
+ tabulatorOptions: null,
+ tabulatorEvents: [],
+ zeitsperreData: {}
+ };
+ },
+ methods: {
+ actionNewZeitsperre(){
+ console.log("actionNewZeitsperre ");
+ },
+ actionEditZeitsperre(zeitsperre_id){
+ console.log("actionEditZeitsperre " + zeitsperre_id);
+ },
+ actionDeleteZeitsperre(zeitsperre_id){
+ console.log("actionDeleteZeitsperre " + zeitsperre_id);
+ },
+ },
+ created() {
+ this.$api.call(ApiAuthinfo.getAuthUID()).then(res => {
+ this.uid = res.data.uid;
+ //TODO(Manu) check if uid via props is better
+ this.tabulatorOptions = {
+ ajaxURL: 'dummy',
+ ajaxRequestFunc: () =>
+ this.$api.call(ApiTimelocks.getTimelocksUser(this.uid)),
+ ajaxResponse: (url, params, response) => response.data,
+ columns: [
+ {title:"beschreibung", field:"beschreibung"},
+ {title:"Grund", field:"zeitsperretyp_kurzbz"},
+ {title:"Von", field:"vondatum",
+ formatter: function (cell) {
+ const dateStr = cell.getValue();
+ if (!dateStr) return "";
+
+ const date = new Date(dateStr);
+ return date.toLocaleString("de-DE", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
+ });
+ }
+ },
+ {title:"Bis", field:"bisdatum",
+ formatter: function (cell) {
+ const dateStr = cell.getValue();
+ if (!dateStr) return "";
+
+ const date = new Date(dateStr);
+ return date.toLocaleString("de-DE", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
+ });
+ }
+ },
+ {title:"vonstunde", field:"vonstunde", visible: false},
+ {title:"bisstunde", field:"bisstunde", visible: false},
+ {title:"Vertretung", field:"vertretung_uid"},
+ {title:"Erreichbarkeit", field:"erreichbarkeit_kurzbz"},
+ {title:"zeitsperre_id", field:"zeitsperre_id", visible: false},
+ {title:"mitarbeiter_uid", field:"mitarbeiter_uid", visible: false},
+ {title: 'Aktionen', field: 'actions',
+ minWidth: 150, // Ensures Action-buttons will be always fully displayed
+ formatter: (cell, formatterParams, onRendered) => {
+ let container = document.createElement('div');
+ container.className = "d-flex gap-2";
+
+ let button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('person', 'bankvb_edit');
+ button.addEventListener('click', (event) =>
+ this.actionEditZeitsperre(cell.getData().zeitsperre_id)
+ );
+ container.append(button);
+
+ button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('person', 'bankvb_delete');
+ button.addEventListener('click', () =>
+ this.actionDeleteZeitsperre(cell.getData().zeitsperre_id)
+ );
+ container.append(button);
+
+ return container;
+ },
+ frozen: true
+ },
+ ]
+ };
+ });
+
+ this.$api
+ .call(ApiTimelocks.getTypenZeitsperren())
+ .then(result => {
+ this.listTypenZeitsperren = result.data;
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+
+ },
+
+/* created(){
+ this.$api
+ .call(ApiAuthinfo.getAuthUID())
+ .then(res => {
+ this.uid = res.data.uid;
+ });
+
+
+ },*/
+ /*
+
+ :label="$p.t('global/name')"
+
+ :new-btn-label="this.$p.t('profil', 'zeitsperren')"
+ {title:"bezeichnung", field:"bezeichnung"},
+ {title:"updateamum", field:"updateamum"},
+ {title:"updatevon", field:"updatevon"},
+ {title:"insertamum", field:"insertamum"},
+ {title:"insertvon", field:"insertvon"},
+ {title:"freigabevon", field:"freigabevon"},
+ {title:"freigabeamum", field:"freigabeamum"},
+ */
+
+ template: /* html */`
+
+
Meine Zeitsperren ({{uid}})
+
+ {{zeitsperreData}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+};
\ No newline at end of file