diff --git a/application/controllers/api/frontend/v1/dropdowns/Dropdown.php b/application/controllers/api/frontend/v1/dropdowns/Dropdown.php
new file mode 100644
index 000000000..839d30fd7
--- /dev/null
+++ b/application/controllers/api/frontend/v1/dropdowns/Dropdown.php
@@ -0,0 +1,51 @@
+.
+ */
+
+if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+/**
+ * This controller operates between (interface) the JS (GUI) and the back-end
+ * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
+ */
+class Dropdown extends FHCAPI_Controller
+{
+ /**
+ * Calls the parent's constructor and prepares libraries and phrases
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'getNations' => self::PERM_LOGGED
+ ]);
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ }
+
+ public function getNations($searchString=null)
+ {
+ $this->load->model('codex/nation_model', 'NationModel');
+
+ $result = $this->NationModel->searchNations($searchString);
+ if (isError($result)) {
+ $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess($result ?: []);
+ }
+}
\ No newline at end of file
diff --git a/application/controllers/api/frontend/v1/stv/Address.php b/application/controllers/api/frontend/v1/stv/Address.php
index d14111e99..fcac421b8 100644
--- a/application/controllers/api/frontend/v1/stv/Address.php
+++ b/application/controllers/api/frontend/v1/stv/Address.php
@@ -42,11 +42,15 @@ class Address extends FHCAPI_Controller
{
$this->load->model('codex/Nation_model', 'NationModel');
- $this->NationModel->addOrder('kurztext');
+ //show at first entries staatenlos and Stbg. ungeklaert
+ $this->db->order_by("kontinent IS NULL DESC, kurztext ASC", '', FALSE);
+ $this->NationModel->addSelect("langtext as label");
+ $this->NationModel->addSelect('kurztext');
+ $this->NationModel->addSelect('nation_code');
$result = $this->NationModel->load();
$data = $this->getDataOrTerminateWithError($result);
-
+
$this->terminateWithSuccess($data);
}
diff --git a/application/models/codex/Nation_model.php b/application/models/codex/Nation_model.php
index ee38c9051..6c7e333d0 100644
--- a/application/models/codex/Nation_model.php
+++ b/application/models/codex/Nation_model.php
@@ -11,4 +11,39 @@ class Nation_model extends DB_Model
$this->dbTable = 'bis.tbl_nation';
$this->pk = 'nation_code';
}
+
+ public function searchNations($filter=null)
+ {
+ $params = [];
+
+ if ($filter)
+ {
+ if (preg_match('/%[0-9A-Fa-f]{2}/', $filter)) {
+ $filter = urldecode($filter);
+ }
+ $filter = mb_strtolower($filter, 'UTF-8'); //for umlaute
+ }
+
+ $qry = "
+ SELECT
+ n.nation_code, n.langtext as label, n.kurztext, n.sperre
+ FROM
+ bis.tbl_nation n";
+
+ if ($filter)
+ {
+ $escapedFilter = $this->db->escape('%' . $filter . '%');
+
+ $qry .= "
+ WHERE
+ n.kurztext ILIKE $escapedFilter
+ OR n.engltext ILIKE $escapedFilter
+ OR n.nation_code ILIKE $escapedFilter
+ ";
+ }
+
+ $qry .= " ORDER BY n.kontinent IS NULL DESC, n.kurztext ASC";
+
+ return $this->execQuery($qry, $params);
+ }
}
diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php
index 5b6138ff8..71c83c76b 100644
--- a/application/views/Studentenverwaltung.php
+++ b/application/views/Studentenverwaltung.php
@@ -21,7 +21,8 @@
'public/css/components/primevue.css',
'public/css/Studentenverwaltung.css',
'public/css/components/function.css',
- 'public/css/components/Detailheader.css'
+ 'public/css/components/Detailheader.css',
+ 'public/css/components/dropdown.css'
],
'customJSs' => [
'vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js',
diff --git a/public/css/components/dropdown.css b/public/css/components/dropdown.css
new file mode 100644
index 000000000..20d0b3caa
--- /dev/null
+++ b/public/css/components/dropdown.css
@@ -0,0 +1,3 @@
+.item-sperre {
+ text-decoration: line-through;
+}
\ No newline at end of file
diff --git a/public/js/api/dropdowns/dropdown.js b/public/js/api/dropdowns/dropdown.js
new file mode 100644
index 000000000..03efcf86a
--- /dev/null
+++ b/public/js/api/dropdowns/dropdown.js
@@ -0,0 +1,25 @@
+/**
+ * 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 {
+ getNations(searchString) {
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/dropdowns/dropdown/getNations/' + searchString
+ };
+ }
+};
diff --git a/public/js/components/Dropdowns/NationsDropdown.js b/public/js/components/Dropdowns/NationsDropdown.js
new file mode 100644
index 000000000..a69879c24
--- /dev/null
+++ b/public/js/components/Dropdowns/NationsDropdown.js
@@ -0,0 +1,109 @@
+import CoreForm from '../Form/Form.js';
+import FormInput from '../Form/Input.js';
+import ApiDropdowns from '../../api/dropdowns/dropdown.js';
+
+export default {
+ name: "NationsDropdown",
+ components: {
+ CoreForm,
+ FormInput
+ },
+ inject: {
+ lists: {
+ from: 'lists'
+ },
+ },
+ props: {
+ nation: {
+ type: String,
+ required: true
+ },
+ containerClass: {
+ type: String,
+ required: false
+ },
+ labelDropdown: {
+ type: String,
+ required: false
+ },
+ nullLabel: {
+ type: String,
+ required: false,
+ default: ''
+ },
+ },
+ data(){
+ return {
+ filteredNations: [],
+ selectedNation: null,
+ abortController: {
+ nations: null
+ },
+ };
+ },
+ watch: {
+ nation: {
+ immediate: true,
+ handler(newVal) {
+ if (newVal) {
+ this.updateNation(newVal);
+ }
+ }
+ },
+ selectedNation(newVal) {
+ //emit
+ this.$emit('updateNation', {
+ nation_code: newVal?.nation_code
+ });
+ }
+ },
+ methods: {
+ filterNations(event){
+ //use search function instead of filteringList to get also params of engltext and nation_code
+ if (this.abortController.nations) {
+ this.abortController.nations.abort();
+ }
+ this.abortController.nations = new AbortController();
+
+ return this.$api
+ .call(ApiDropdowns.getNations(event.query))
+ .then(result => {
+ this.filteredNations = result.data.retval;
+ });
+ },
+ updateNation(nation) {
+ const detailsNation = this.lists.nations.find(
+ item => item.nation_code == nation
+ );
+
+ //create new object to avoid erros because of same instance if included more than once
+ this.selectedNation = detailsNation
+ ? { ...detailsNation }
+ : { nation_code: nation, label: this.nullLabel };
+ },
+ },
+ template: `
+
+
+
+
+ {{slotProps.option.label}}
+
+
+
+
`
+};
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Details.js
index 0b5eec44d..23c94c540 100644
--- a/public/js/components/Stv/Studentenverwaltung/Details/Details.js
+++ b/public/js/components/Stv/Studentenverwaltung/Details/Details.js
@@ -3,17 +3,18 @@ import FormInput from '../../../Form/Input.js';
import FormUploadImage from '../../../Form/Upload/Image.js';
import CoreUdf from '../../../Udf/Udf.js';
+import NationsDropdown from '../../../Dropdowns/NationsDropdown.js';
import ApiStvDetails from '../../../../api/factory/stv/details.js';
-
export default {
name: "TabDetails",
components: {
CoreForm,
FormInput,
FormUploadImage,
- CoreUdf
+ CoreUdf,
+ NationsDropdown
},
inject: {
showBpk: {
@@ -54,11 +55,14 @@ export default {
default: {}
}
},
+ emits: [
+ 'updateNation'
+ ],
data() {
return {
original: null,
data: null,
- changed: {}
+ changed: {},
}
},
computed: {
@@ -79,7 +83,7 @@ export default {
"v": this.$p.t('person', 'verheiratet'),
"w": this.$p.t('person', 'verwitwet'),
};
- }
+ },
},
watch: {
modelValue(n) {
@@ -100,7 +104,7 @@ export default {
this.changed = res;
},
deep: true
- }
+ },
},
methods: {
updateStudent(n) {
@@ -168,6 +172,12 @@ export default {
const bodyEncoded = encodeURIComponent(bodyWithNewLines);
window.location.href = "mailto:" + this.modelValue.mail_intern + "?subject=" + subjectEncoded + "&body=" + bodyEncoded;
+ },
+ handleChangeNation({nation_code}){
+ this.data.geburtsnation = nation_code;
+ },
+ handleChangeStbg({nation_code}){
+ this.data.staatsbuergerschaft = nation_code;
}
},
created() {
@@ -325,28 +335,26 @@ export default {
maxlength="128"
>
-
-
-
-
-
+
+
-
-
-
+ >
+
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Kontakt/Address.js b/public/js/components/Stv/Studentenverwaltung/Details/Kontakt/Address.js
index 7e73b13d2..016b9c600 100644
--- a/public/js/components/Stv/Studentenverwaltung/Details/Kontakt/Address.js
+++ b/public/js/components/Stv/Studentenverwaltung/Details/Kontakt/Address.js
@@ -4,6 +4,7 @@ import FhcFormValidation from '../../../../Form/Validation.js';
import BsModal from "../../../../Bootstrap/Modal.js";
import FormForm from '../../../../Form/Form.js';
import FormInput from '../../../../Form/Input.js';
+import NationsDropdown from '../../../../Dropdowns/NationsDropdown.js';
import ApiStvAddress from '../../../../../api/factory/stv/kontakt/address.js';
@@ -15,11 +16,15 @@ export default{
FhcFormValidation,
BsModal,
FormForm,
- FormInput
+ FormInput,
+ NationsDropdown
},
props: {
uid: Number
},
+ emits: [
+ 'updateNation'
+ ],
data() {
return {
addressData: {
@@ -231,7 +236,6 @@ export default{
// delete this.addressData.plz;
this.loadPlaces(this.addressData.address.plz);
this.$refs.adressModal.show();
-
}
});
},
@@ -338,6 +342,9 @@ export default{
this.statusNew = true;
},
+ handleChangeNation({nation_code}){
+ this.addressData.nation = nation_code;
+ },
},
created() {
this.$api
@@ -397,182 +404,174 @@ export default{
v-model="addressData.strasse"
>
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
- {{$p.t('ui', 'bittePlzWaehlen')}}
+
+
+
+
+
+
+
+
-
-
-
-
-
+ >
+
+
+
+ v-else
+ type="text"
+ :label="$p.t('person/ort')"
+ name="ort"
+ v-model="addressData.ort"
+ >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Mobility/Mobility.js b/public/js/components/Stv/Studentenverwaltung/Details/Mobility/Mobility.js
index dd2899bf1..435cdb135 100644
--- a/public/js/components/Stv/Studentenverwaltung/Details/Mobility/Mobility.js
+++ b/public/js/components/Stv/Studentenverwaltung/Details/Mobility/Mobility.js
@@ -4,6 +4,7 @@ import FormForm from '../../../../Form/Form.js';
import FormInput from '../../../../Form/Input.js';
import MobilityPurpose from './List/Purpose.js';
import MobilitySupport from './List/Support.js';
+import NationsDropdown from '../../../../Dropdowns/NationsDropdown.js';
import ApiStvMobility from '../../../../../api/factory/stv/mobility.js';
@@ -14,7 +15,8 @@ export default {
FormForm,
FormInput,
MobilityPurpose,
- MobilitySupport
+ MobilitySupport,
+ NationsDropdown
},
inject: {
$reloadList: {
@@ -35,6 +37,15 @@ export default {
props: {
student: Object
},
+ emits: [
+ 'updateNation',
+ 'deleteMobilityPurpose',
+ 'setMobilityPurpose',
+ 'setMobilityPurposeToNewMobility',
+ 'deleteMobilitySupport',
+ 'setMobilitySupport',
+ 'setMobilitySupportToNewMobility'
+ ],
data() {
return {
formData: {
@@ -392,6 +403,14 @@ export default {
addSupportToMobility({aufenthaltfoerderung_code}){
this.formData.localSupports.push(aufenthaltfoerderung_code);
},
+ handleChangeGastnation({nation_code}){
+ console.log("update Gastnation with" + nation_code);
+ this.formData.nation_code = nation_code;
+ },
+ handleChangeHerkunftsland({nation_code}){
+ console.log("update erkunftsland with" + nation_code);
+ this.formData.herkunftsland_code = nation_code;
+ }
},
created() {
this.$api
@@ -429,6 +448,24 @@ export default {
})
.catch(this.$fhcAlert.handleSystemError);
},
+ /*
+ *
+
+
+ * */
template: `
In / Out
@@ -559,66 +596,59 @@ export default {
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Prestudent.js b/public/js/components/Stv/Studentenverwaltung/Details/Prestudent.js
index 1d8d5ac26..473d14193 100644
--- a/public/js/components/Stv/Studentenverwaltung/Details/Prestudent.js
+++ b/public/js/components/Stv/Studentenverwaltung/Details/Prestudent.js
@@ -3,6 +3,7 @@ import FormInput from '../../../Form/Input.js';
import TblHistory from "./Prestudent/History.js";
import CoreUdf from '../../../Udf/Udf.js';
+import NationsDropdown from '../../../Dropdowns/NationsDropdown.js';
import ApiStvPrestudent from '../../../../api/factory/stv/prestudent.js';
@@ -12,7 +13,8 @@ export default {
FormForm,
FormInput,
TblHistory,
- CoreUdf
+ CoreUdf,
+ NationsDropdown
},
inject: {
lists: {
@@ -58,6 +60,9 @@ export default {
default: {}
}
},
+ emits: [
+ 'updateNation'
+ ],
data() {
return {
data: [],
@@ -178,6 +183,15 @@ export default {
item.label.toLowerCase().includes(query)
)
},
+ handleChangeZGVNation({nation_code}){
+ this.data.zgvnation = nation_code;
+ },
+ handleChangeZGVMaNation({nation_code}){
+ this.data.zgvmanation = nation_code;
+ },
+ handleChangeZGVDrNation({nation_code}){
+ this.data.zgvdoktornation = nation_code;
+ },
},
async created() {
await this.loadPrestudent();
@@ -336,18 +350,15 @@ export default {
:teleport="true"
>
-
-
-
-
-
+
-
-
-
-
-
+
@@ -467,18 +475,15 @@ export default {
:teleport="true"
>
-
-
-
-
-
+