allows user to make profil changes requests and to oversee his requested changes

This commit is contained in:
SimonGschnell
2024-01-15 15:15:16 +01:00
parent d3a3ebacfc
commit e881abe904
8 changed files with 653 additions and 297 deletions
+44 -7
View File
@@ -19,7 +19,8 @@ class Profil extends Auth_Controller
'index' => ['student/anrechnung_beantragen:r', 'user:r'], // TODO(chris): permissions?
'foto_sperre_function' => ['student/anrechnung_beantragen:r', 'user:r'],
'getView' => ['student/anrechnung_beantragen:r', 'user:r'],
'editProfil' => ['student/anrechnung_beantragen:r', 'user:r'],
'insertProfilRequest' => ['student/anrechnung_beantragen:r', 'user:r'],
'updateProfilRequest' => ['student/anrechnung_beantragen:r', 'user:r'],
]);
@@ -67,13 +68,13 @@ class Profil extends Auth_Controller
public function editProfil()
public function insertProfilRequest()
{
$json = json_decode($this->input->raw_input_stream);
$data = ["uid" => $this->uid, "requested_change" => json_encode($json->payload), "change_timestamp" => "NOW()", "topic"=>$json->topic];
$data = ["topic"=>$json->topic,"uid" => $this->uid, "requested_change" => json_encode($json->payload), "change_timestamp" => "NOW()" ];
//? gets all the requested changes from a user
$res = $this->ProfilChangeModel->loadWhere(["uid"=>$this->uid]);
@@ -81,13 +82,14 @@ class Profil extends Auth_Controller
//? checks if the user already made a request to change a topic
//! which is an constraint added to the public.tbl_cis_profil_update table
if($res){
foreach($res as $update_request){
if($update_request->topic == $json->topic && $update_request->uid == $this->uid){
echo json_encode(error("uid and topic combination exists already"));
return;
}
}
}}
$insert_res = $this->ProfilChangeModel->insert($data);
@@ -119,6 +121,32 @@ class Profil extends Auth_Controller
}
public function updateProfilRequest()
{
$json = json_decode($this->input->raw_input_stream);
$data = ["topic"=>$json->topic,"uid" => $this->uid, "requested_change" => json_encode($json->payload), "change_timestamp" => "NOW()" ];
//? gets all the requested changes from a user
if(isSuccess($this->ProfilChangeModel->addSelect(["profil_update_id"])) ){
$requestID = $this->ProfilChangeModel->loadWhere(["uid"=>$this->uid,"topic"=>$json->topic]);
$requestID = hasData($requestID) ? getData($requestID)[0]->profil_update_id : null;
};
$update_res =$this->ProfilChangeModel->update([$requestID],$data);
if(isError($update_res)){
//catch error
}else{
$editTimestamp = $this->ProfilChangeModel->getTimestamp($update_res->retval[0]);
$update_res->retval = date_create($editTimestamp)->format('d.m.Y');
echo json_encode($update_res);
}
}
private function viewMitarbeiterProfil($uid)
@@ -414,7 +442,7 @@ class Profil extends Auth_Controller
if (
isSuccess($adresse_res = $this->AdresseModel->addSelect(array("strasse", "tbl_adressentyp.bezeichnung as adr_typ", "plz", "ort"))) &&
isSuccess($adresse_res = $this->AdresseModel->addSelect(["adresse_id","strasse", "tbl_adressentyp.bezeichnung as adr_typ", "plz", "ort"])) &&
isSuccess($adresse_res = $this->AdresseModel->addOrder("zustelladresse", "DESC")) &&
isSuccess($adresse_res = $this->AdresseModel->addOrder("sort")) &&
isSuccess($adresse_res = $this->AdresseModel->addJoin("tbl_adressentyp", "typ=adressentyp_kurzbz"))
@@ -565,7 +593,11 @@ class Profil extends Auth_Controller
$res->standort_telefon = $telefon_res;
$res->profilUpdates = $profilUpdates?: null;
if($res->profilUpdates){
foreach($res->profilUpdates as $update){
$update->requested_change = json_decode($update->requested_change);
$update->change_timestamp = date_create($update->change_timestamp)->format('d.m.Y');
}}
return $res;
}
@@ -623,7 +655,7 @@ class Profil extends Auth_Controller
if (
isSuccess($adresse_res = $this->AdresseModel->addSelect(array("strasse", "tbl_adressentyp.bezeichnung as adr_typ", "plz", "ort"))) &&
isSuccess($adresse_res = $this->AdresseModel->addSelect(["adresse_id","strasse", "tbl_adressentyp.bezeichnung as adr_typ", "plz", "ort"])) &&
isSuccess($adresse_res = $this->AdresseModel->addOrder("zustelladresse", "DESC")) &&
isSuccess($adresse_res = $this->AdresseModel->addOrder("sort")) &&
isSuccess($adresse_res = $this->AdresseModel->addJoin("tbl_adressentyp", "typ=adressentyp_kurzbz"))
@@ -767,6 +799,11 @@ class Profil extends Auth_Controller
$res->mailverteiler = $mailverteiler_res;
$res->profilUpdates = $profilUpdates?: null;
if($res->profilUpdates){
foreach($res->profilUpdates as $update){
$update->requested_change = json_decode($update->requested_change);
$update->change_timestamp = date_create($update->change_timestamp)->format('d.m.Y');
}}
return $res;
+5 -6
View File
@@ -50,6 +50,9 @@
align-content: space-between;
}
.form-underline .form-underline-content{
border-width: 1px;
border-color: transparent transparent #dee2e6 transparent;
@@ -75,11 +78,7 @@
}
option:checked{
background: linear-gradient(#005485, #005485);
}
#SelectStyle{
}
+9 -2
View File
@@ -3,9 +3,16 @@ export default {
//! API Calls for Profil Views
editProfil: function(topic, payload) {
insertProfilRequest: function(topic, payload) {
const url = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router+
`/Cis/Profil/editProfil`;
`/Cis/Profil/insertProfilRequest`;
return axios.post(url,{topic, payload});
},
updateProfilRequest: function(topic, payload) {
const url = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router+
`/Cis/Profil/updateProfilRequest`;
return axios.post(url,{topic, payload});
},
+49 -95
View File
@@ -1,14 +1,14 @@
import BsModal from "../../Bootstrap/Modal.js";
import Alert from "../../Bootstrap/Alert.js";
import BreadCrumb from "../Selection/Breadcrumb.js";
import Select from "../Selection/Select.js";
import EditProfilSelect from "./EditProfilSelect.js";
export default {
components: {
BsModal,
Alert,
BreadCrumb,
Select,
EditProfilSelect,
},
mixins: [BsModal],
props: {
@@ -37,6 +37,8 @@ export default {
privateKontakte:[{strasse:"strasse1",plz:100},{strasse:"strasse1",plz:100},{strasse:"strasse1",plz:100}],
privateAdressen:[{kontakt:"telefon",anmerkung:"1"},{kontakt:"email",anmerkung:"2"},{kontakt:"telefon",anmerkung:"3"}]
},
testSelectedItems:[],
profilUpdate:null,
topic:null,
@@ -58,12 +60,11 @@ export default {
},
methods: {
testEvent: function(){
if(!this.propertySelected){
this.testListe = this.testListe[this.testValue];
this.propertySelected = true;
}
selectEvent: function (option){
this.editData = this.editData[option];
},
createDeepCopy: function(object){
//? using Vue.toRaw because deep clones with structuredClone can not be done on proxies
@@ -83,11 +84,12 @@ export default {
//* only inserts new row if the inputField value is different from the original value
if(this.isInputFieldChanged && this.topic){
if(this.topic && this.profilUpdate){
//? inserts new row in public.tbl_cis_profil_update
Vue.$fhcapi.UserData.editProfil(this.topic,this.inputField).then((res)=>{
if(this.editData.update){
Vue.$fhcapi.UserData.updateProfilRequest(this.topic,this.profilUpdate).then((res)=>{
this.result = {
editData: this.editData,
timestamp: res.data.retval,
@@ -102,116 +104,68 @@ export default {
}
//
});
//
}
}else{
Vue.$fhcapi.UserData.insertProfilRequest(this.topic,this.profilUpdate).then((res)=>{
this.result = {
editData: this.editData,
timestamp: res.data.retval,
};
this.hide();
if(res.data.error == 0){
Alert.popup("Ihre Anfrage wurde erfolgreich gesendet. Bitte warten Sie, während sich das Team um Ihre Anfrage kümmert.");
}else{
Alert.popup("Ein Fehler ist aufgetreten: "+ JSON.stringify(res.data.retval));
}
//
});
}
}
},
},
computed: {
isInputFieldChanged: function(){
if(this.inputField){
return JSON.stringify(this.inputField) !== JSON.stringify(this.secondSelectedOption);
}
return false;
},
firstSelection(){
return Object.keys(this.value);
},
secondSelection(){
switch(this.firstSelectedOption){
case "Personen_Informationen": return Object.keys(this.editData[this.firstSelectedOption]);
case "Private_Kontakte": return this.editData[this.firstSelectedOption];
case "Private_Adressen": return this.editData[this.firstSelectedOption];
default: return [];
}
},
},
created() {
if(this.editData.topic){
//? if the topic was passed through the prop add it to the reactive data
this.topic = this.editData.topic;
}
},
mounted() {
this.modal = this.$refs.modalContainer.modal;
},
popup(options) {
console.log("popup start");
return BsModal.popup.bind(this)(null, options);
},
template: `
<bs-modal ref="modalContainer" v-bind="$props" body-class="" dialog-class="modal-lg" class="bootstrap-alert" backdrop="false" >
<template v-slot:title>
{{"Profil bearbeiten" }}
<template v-slot:title>
{{"Profil bearbeiten" }}
</template>
<template v-slot:default>
<bread-crumb :list="['this','is a','test']" ></bread-crumb>
<p>{{testValue}}</p>
<Select ariaLabel="test" v-model="testValue" @select="testEvent" :list="testListe"></Select>
<!-- DONT FORGET TO UNCOMMENT THIS -->
<!-- Breadcrumbs
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item" v-if="firstSelectedOption">{{firstSelectedOption}}</li>
<li class="breadcrumb-item" v-if="secondSelectedOption" >{{firstSelectedOption ==="Personen_Informationen" ? Object.keys(secondSelectedOption)[0] : secondSelectedOptionIndex+1 }}</li>
</ol>
</nav>
-->
<edit-profil-select v-model:topic="topic" v-model:profilUpdate="profilUpdate" ariaLabel="test" :list="editData"></edit-profil-select>
<select v-if="!firstSelectedOption" v-model="firstSelectedOption" class="form-select" size="3" aria-label="size 3 select example">
<option v-for="(option,index) in firstSelection" :value="option">{{option.replace("_"," ")}}</option>
</select>
<select v-if="firstSelectedOption && !secondSelectedOption" class="form-select" size="3" aria-label="size 3 select example">
<option @click="
if(Array.isArray(editData[firstSelectedOption])){
secondSelectedOptionIndex = index;
secondSelectedOption = createDeepCopy(option);
inputField= createDeepCopy(option);
//* topic is the property in which the array is stored when it is an array
topic = firstSelectedOption;
}else{
secondSelectedOption={[option]:editData[firstSelectedOption][option]};
inputField={[option]:editData[firstSelectedOption][option]};
//* topic is the selected property if is an object
topic = option;
}" v-for="(option, index) in secondSelection" :value="option"><div v-if="typeof(option)==='object'">
<div class="row m-2" v-for="(value,property) in option">
<div class="col"><span>{{property}}</span></div>
<div class="col"><span>{{value}}</span></div>
</div>
</div>
<template v-else>{{option}}</template>
</option>
</select>
<div v-if="inputField">
<div v-for="(field,index) in inputField">
<div class="form-underline">
<div class="form-underline-titel">{{index}}</div>
<input class="form-control" :id="index" :value="inputField[index]" @input="changeInput($event,inputField,index)" :placeholder="field">
</div>
</div>
</div>
</template>
<!-- optional footer -->
<template v-slot:footer>
<button class="btn btn-outline-danger " @click="hide">Abbrechen</button>
<!--<p v-if="editTimestamp" class="flex-fill">Letzte Anfrage: {{editTimestamp}}</p>-->
<button v-if="isInputFieldChanged" @click="submitProfilChange" role="button" class="btn btn-primary">Senden</button>
<button v-if="profilUpdate" @click="submitProfilChange" role="button" class="btn btn-primary">Senden</button>
</template>
<!-- end of optional footer -->
</bs-modal>`,
@@ -0,0 +1,124 @@
import {Kontakt, EditKontakt, Adresse, EditAdresse} from "./ProfilComponents.js";
export default {
components: {
Kontakt,
EditKontakt,
Adresse,
EditAdresse,
},
props: {
//! this should throw an error in the js console, have to check later
list:Object,
//? Prop used to determine how many options the select should initially show
size:{
type:Number,
default: null,
},
//? Content for the aria label of the select
ariaLabel:{
type:String,
required:true,
},
profilUpdate:String,
topic:String,
},
emits:{
//? update:modelValue event is needed to notify the v-model when the value has changed
['update:profilUpdate']:null,
['update:topic']:null,
select:null,
},
data() {
return {
view:null,
data:null,
}
},
methods: {
profilUpdateEmit: function(event){
console.log(event);
//? passes the updated profil information to the parent component
this.$emit('update:profilUpdate',event);
},
updateOptions: function(event, item){
this.data=item.data;
this.view=item.view;
//? emits the selected topic to the parent component
if(item.title){
this.$emit('update:topic',item.title);
}
},
},
computed: {
listLength: function(){
return this.list.length;
},
lastElement: function(){
return this.list[this.list.length-1];
},
computedList: function(){
if(Array.isArray(this.list)){
//? the passed data is an array
return this.list;
}else if(typeof(this.list) === 'object' && this.list !== null){
//? the passed data is an object
return Object.keys(this.list);
}else{
console.warn("The passed data is neither an Array or an Object");
return null;
//! the passed data is neither an object or an array
}
}
},
created() {
this.data = JSON.parse(JSON.stringify(this.list.data));
this.view = JSON.parse(JSON.stringify(this.list.view));
//? sets the default length of the options to show equal to the number of elements in the list
if(!this.optionLength){
//? if it is an object, then it will take the length of the object keys, otherwise it takes the normal length
this.optionLength = this.computedList.length;
}
},
mounted() {
},
template: `
<div v-if="!view" class="list-group">
<button type="button" class=" list-group-item list-group-item-action" @click="updateOptions($event,item)" v-for="item in data">
<p v-if="item.title" class="my-1" >{{item.title}}</p>
<!-- this is used for multiple elements in the select -->
<component class="my-2" :is="item.listview" v-bind="item"></component>
</button>
</div>
<div v-else-if="view==='text_input'" class="form-underline">
<div class="form-underline-titel">{{data.titel?data.titel:'titel'}}</div>
<input class="form-control" @input="$emit('update:profilUpdate',data.value)" v-model="data.value" :placeholder="data.value">
</div>
<!-- if it not a normal text input field then reder the custom edit input component -->
<!-- custom component is required to emit an profilUpdate event to register the new entered value -->
<template v-else>
<component @profilUpdate="profilUpdateEmit" :is="view" :data="data"></component>
</template>
`,
};
@@ -1,14 +1,16 @@
import { CoreFilterCmpt } from "../../../components/filter/Filter.js";
import EditProfil from "./EditProfil.js"
import EditProfil from "./EditProfil.js";
import {Adresse, Kontakt, FetchProfilUpdates} from "./ProfilComponents.js";
export default {
components: {
CoreFilterCmpt,
EditProfil,
Adresse,
Kontakt,
FetchProfilUpdates,
},
data() {
return {
@@ -260,24 +262,65 @@ export default {
created() {
if(!this.data.editData){
this.data.editData = {
Personen_Informationen : {...this.personData, vorname: this.data.vorname, nachname: this.data.nachname},
Private_Kontakte: this.data.kontakte,
Private_Adressen:this.privateAdressen,
view:null,
data:{
Personen_Informationen : {
title:"Personen Informationen",
view:null,
data:{
username:{
title:"username",
view:"text_input",
data:{
titel:"username",
value:this.data.username,
}
},
vorname: {
title:"vorname",
view:"text_input",
data:{
titel:"vorname",
value:this.data.vorname,
}},
nachname: {
title:"nachname",
view:"text_input",
data:{
titel:"nachname",
value:this.data.nachname,
}
}
}
},
Private_Kontakte: {
title:"Private Kontakte" ,
data:this.privateKontakte.map(kontakt => {
return {
listview:'Kontakt',
view:'EditKontakt',
data:kontakt
}})
},
Private_Adressen: {
title: "Private Adressen",
data:this.privateAdressen.map(kontakt => {
return {
listview:'Adresse',
view:'EditAdresse',
data:kontakt
}})
},
},
};
}else{
this.data.editData = {
Personen_Informationen : {...this.personData, vorname: this.data.vorname, nachname: this.data.nachname},
Private_Kontakte: this.data.kontakte,
Private_Adressen:this.privateAdressen,
};
}
console.log(JSON.stringify(this.data.editData,null,2));
},
mounted() {
@@ -335,7 +378,7 @@ export default {
<div class="card-header">
Profil Informations Änderungen Anfragen</div>
<div class="card-body">
<p v-for="update in data.profilUpdates">{{update.requested_change}}</p>
<fetch-profil-updates></fetch-profil-updates>
</div>
</div>
@@ -629,39 +672,9 @@ export default {
<div class="gy-3 row ">
<div v-for="element in privateKontakte" class="col-12">
<div class="gy-3 row align-items-center justify-content-center">
<div class="col-1 text-center" >
<i class="fa-solid " :class="{...(element.kontakt.includes('@')?{'fa-envelope':true}:{'fa-phone':true})}" style="color:rgb(0, 100, 156)"></i>
</div>
<div :class="{...(element.anmerkung? {'col-11':true, 'col-md-6':true, 'col-xl-11':true, 'col-xxl-6':true} : {'col-10':true, 'col-xl-9':true, 'col-xxl-10':true})}">
<!-- rendering KONTAKT emails -->
<div class="form-underline ">
<div class="form-underline-titel">{{element.kontakttyp}}</div>
<a :href="'mailto:'+element.kontakt" v-if="element.kontakt.includes('@')" class="form-underline-content">{{element.kontakt}} </a>
<a v-else :href="'tel:'+element.kontakt" class="form-underline-content">{{element.kontakt}} </a>
</div>
</div>
<div v-if="element?.anmerkung" class="offset-1 offset-md-0 offset-xl-1 offset-xxl-0 order-2 order-sm-1 col-10 col-md-4 col-xl-9 col-xxl-4 ">
<div class="form-underline ">
<div class="form-underline-titel">Anmerkung</div>
<span class="form-underline-content">{{element.anmerkung}} </span>
</div>
</div>
<div class="col-1 col-sm-1 order-2 order-lg-1 col-xl-2 col-xxl-1 allign-middle">
<i v-if="element.zustellung" class="fa-solid fa-check"></i>
<i v-else="element.zustellung" class="fa-solid fa-xmark"></i>
</div>
</div>
<Kontakt :data="element"></Kontakt>
</div>
</div>
</div>
@@ -675,60 +688,20 @@ export default {
<div class="col">
<div class="card">
<div class="card-header">Private Adressen</div>
<div class="card-body">
<div class="gy-3 row ">
<div v-for="element in privateAdressen" class="col-12">
<div class="gy-3 row justify-content-center align-items-center">
<div class="card-body">
<!-- column 1 in the address row -->
<div class="col-1 text-center">
<div class="gy-3 row ">
<div v-for="element in privateAdressen" class="col-12">
<Adresse :data="element"></Adresse>
<i class="fa fa-location-dot fa-lg" style="color:#00649C "></i>
</div>
<div class="col-11 col-sm-8 col-xl-11 col-xxl-8 order-1">
<div class="form-underline ">
<div class="form-underline-titel">Strasse</div>
<span class="form-underline-content">{{element.strasse}} </span>
</div>
</div>
<!-- column 2 in the address row -->
<div class="offset-1 offset-sm-0 offset-xl-1 offset-xxl-0 order-2 order-sm-4 order-xl-2 order-xxl-4 col-11 col-sm-5 col-xl-11 col-xxl-5 ">
<div class="form-underline ">
<div class="form-underline-titel">Typ</div>
<span class="form-underline-content">{{element.adr_typ}} </span>
</div>
</div>
<div class="offset-1 order-3 order-sm-3 col-11 col-sm-6 col-xl-7 col-xxl-6 ">
<div class="form-underline ">
<div class="form-underline-titel">Ort</div>
<span class="form-underline-content">{{element.ort}} </span>
</div>
</div>
<div class="offset-1 offset-sm-0 order-4 order-sm-2 order-xl-4 order-xxl-2 col-11 col-sm-3 col-xl-4 col-xxl-3 ">
<div class="form-underline ">
<div class="form-underline-titel">PLZ</div>
<span class="form-underline-content">{{element.plz}} </span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- -->
<!-- -->
@@ -795,11 +768,7 @@ export default {
<div class="card-header">
Profil Updates
</div>
<div class="card-body d-flex justify-content-start flex-wrap">
<!-- -->
<button v-for="update in data.profilUpdates" class="btn m-1" :class="{'btn-outline-primary':(update.topic !== 'Private_Kontakte' || update.topic !== 'Private_Adressen'), 'btn-outline-danger':update.topic == 'Private_Kontakte', 'btn-outline-success':update.topic == 'Private_Adressen'}" ><i class="fa fa-edit"></i> {{update.topic}}</button>
</div>
<fetch-profil-updates :modal="EditProfil" :data="data.profilUpdates"></fetch-profil-updates>
</div>
@@ -0,0 +1,352 @@
const Adresse = {
props:{data:Object, view:String},
data(){
return{}
},
created(){
},
template:`
<div class="my-2 row justify-content-center align-items-center">
<!-- column 1 in the address row -->
<div class="col-1 text-center">
<i class="fa fa-location-dot fa-lg" style="color:#00649C "></i>
</div>
<div class="col-11 col-sm-8 col-xl-11 col-xxl-8 order-1">
<div class="form-underline ">
<div class="form-underline-titel">Strasse</div>
<span class="form-underline-content">{{data.strasse}} </span>
</div>
</div>
<!-- column 2 in the address row -->
<div class="offset-1 offset-sm-0 offset-xl-1 offset-xxl-0 order-2 order-sm-4 order-xl-2 order-xxl-4 col-11 col-sm-5 col-xl-11 col-xxl-5 ">
<div class="form-underline ">
<div class="form-underline-titel">Typ</div>
<span class="form-underline-content">{{data.adr_typ}} </span>
</div>
</div>
<div class="offset-1 order-3 order-sm-3 col-11 col-sm-6 col-xl-7 col-xxl-6 ">
<div class="form-underline ">
<div class="form-underline-titel">Ort</div>
<span class="form-underline-content">{{data.ort}} </span>
</div>
</div>
<div class="offset-1 offset-sm-0 order-4 order-sm-2 order-xl-4 order-xxl-2 col-11 col-sm-3 col-xl-4 col-xxl-3 ">
<div class="form-underline ">
<div class="form-underline-titel">PLZ</div>
<span class="form-underline-content">{{data.plz}} </span>
</div>
</div>
</div>
`
};
const EditAdresse = {
props:{data:Object},
data(){
return{}
},
methods:{
updateValue: function(event,bind){
this.data[bind] = event.target.value;
this.$emit('profilUpdate',this.data);
},
},
created(){
},
template:`
<div class="gy-3 row justify-content-center align-items-center">
<!-- column 1 in the address row -->
<div class="col-12 col-sm-9 col-xl-12 col-xxl-9 order-1">
<div class="form-underline ">
<div class="form-underline-titel">Strasse</div>
<input class="form-control" :value="data.strasse" @input="updateValue($event,'strasse')" :placeholder="data.strasse">
</div>
</div>
<!-- column 2 in the address row -->
<div class=" order-2 order-sm-4 order-xl-3 order-xxl-4 col-12 col-sm-5 col-xl-8 col-xxl-5 ">
<div class="form-underline ">
<div class="form-underline-titel">Typ</div>
<input class="form-control" :value="data.adr_typ" @input="updateValue($event,'adr_typ')" :placeholder="data.adr_typ">
</div>
</div>
<div class="order-3 order-sm-3 order-xl-2 order-xxl-3 col-12 col-sm-7 col-xl-12 col-xxl-7 ">
<div class="form-underline ">
<div class="form-underline-titel">Ort</div>
<input class="form-control" :value="data.ort" @input="updateValue($event,'ort')" :placeholder="data.ort">
</div>
</div>
<div class="order-4 order-sm-2 order-xl-4 order-xxl-2 col-12 col-sm-3 col-xl-4 col-xxl-3 ">
<div class="form-underline ">
<div class="form-underline-titel">PLZ</div>
<input class="form-control" :value="data.plz" @input="updateValue($event,'plz')" :placeholder="data.plz">
</div>
</div>
</div>
`
};
const Kontakt = {
props:{
view:String,
data:Object,
},
data(){
return {
}
},
created(){
},
template:`
<div class=" row align-items-center justify-content-center">
<div class="col-1 text-center" >
<i class="fa-solid " :class="{...(data.kontakt.includes('@')?{'fa-envelope':true}:{'fa-phone':true})}" style="color:rgb(0, 100, 156)"></i>
</div>
<div :class="{...(data.anmerkung? {'col-11':true, 'col-md-6':true, 'col-xl-11':true, 'col-xxl-6':true} : {'col-10':true, 'col-xl-9':true, 'col-xxl-10':true})}">
<!-- rendering KONTAKT emails -->
<div class="form-underline ">
<div class="form-underline-titel">{{data.kontakttyp}}</div>
<a v-if="data.kontakt.includes('@')" role="link" :aria-disabled="view?true:false" :href="!view?('mailto:'+data.kontakt):null" class="form-underline-content">{{data.kontakt}} </a>
<a v-else role="link" :aria-disabled="view?true:false" :href="!view?('tel:'+data.kontakt):null" class="form-underline-content">{{data.kontakt}} </a>
</div>
</div>
<div v-if="data?.anmerkung" class="offset-1 offset-md-0 offset-xl-1 offset-xxl-0 order-2 order-sm-1 col-10 col-md-4 col-xl-9 col-xxl-4 ">
<div class="form-underline ">
<div class="form-underline-titel">Anmerkung</div>
<span class="form-underline-content">{{data.anmerkung}} </span>
</div>
</div>
<div class="text-center col-1 col-sm-1 order-2 order-lg-1 col-xl-2 col-xxl-1 allign-middle">
<i v-if="data.zustellung" class="fa-solid fa-check"></i>
<i v-else="data.zustellung" class="fa-solid fa-xmark"></i>
</div>
</div>
`,
};
const EditKontakt = {
props:{
data:Object,
},
data(){
return{
}
},
methods:{
updateValue: function(event,bind){
if(bind === 'zustellung'){
this.data[bind] = event.target.checked;
}else{
this.data[bind] = event.target.value;
}
this.$emit('profilUpdate',this.data);
},
},
created(){
console.log(this.$props);
},
template:
`
<div class="gy-3 row align-items-center justify-content-center">
<div class="col-12">
<!-- rendering KONTAKT emails -->
<div class="form-underline">
<div class="form-underline-titel">{{data.kontakttyp}}</div>
<input class="form-control" :value="data.kontakt" @input="updateValue($event,'kontakt')" :placeholder="data.kontakt">
</div>
</div>
<div v-if="data?.anmerkung" class="col-12">
<div class="form-underline">
<div class="form-underline-titel">Anmerkung</div>
<input class="form-control" :value="data.anmerkung" @input="updateValue($event,'anmerkung')" :placeholder="data.anmerkung">
</div>
</div>
<div class="d-flex flex-row justify-content-start col-12 allign-middle">
<span style="opacity: 0.65; font-size: .85rem; " class="px-2">Zustellungs Adresse</span>
<input class="form-check-input " type="checkbox" :checked="data.zustellung" @change="updateValue($event,'zustellung')" id="flexCheckDefault">
</div>
</div>
`
};
//? used to edit already requested profil changes
import EditProfil from "./EditProfil.js";
const FetchProfilUpdates = {
props:{
data:{
type:Object,
},
},
data(){
return {}
},
methods:{
getView: function(topic){
console.log("the topic is here",topic);
switch(topic){
case "Private Kontakte" : return "EditKontakt"; break;
case "Private Adressen" : return "EditAdresse"; break;
default: return "text_input"; break;
}
},
openModal(updateRequest) {
let view = this.getView(updateRequest.topic);
let content =null;
if(view === 'text_input'){
content={
view:view,
data:{
titel:updateRequest.topic,
value:updateRequest.requested_change,
},
update:true,
topic:updateRequest.topic,
}
}else{
content = {
view: view,
data: updateRequest.requested_change,
update:true,
topic:updateRequest.topic,
}
}
//? only show the popup if also the right content is available
if(content){
EditProfil.popup({
value:content,
timestamp:null,
}).then((res) => {
/* if(res.timestamp && res.editData){
this.data.editDataTimestamp = res.timestamp;
this.data.editData = res.editData;
} */
}).catch(e => {
console.log(e);
});
}
},
},
created(){
},
template:`
<table class="table table-sm table-hover">
<thead>
<tr >
<th scope="col">Topic</th>
<th scope="col">Date of Request</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr v-for="item in data">
<td >{{item.topic}}</td>
<td >{{item.change_timestamp}}</td>
<td ><i @click="openModal(item)" role="button" class="fa fa-edit"></i></td>
</tr>
</tbody>
</table>
`
};
export {Adresse, EditAdresse, Kontakt, EditKontakt, FetchProfilUpdates};
@@ -1,86 +0,0 @@
export default {
components: {
},
props: {
//! this should throw an error in the js console, have to check later
list:[Array,Object],
//? prop modelValue allows v-model on custom Components
modelValue:String,
//? Prop used to determine how many options the select should initially show
size:{
type:Number,
default: null,
},
//? Content for the aria label of the select
ariaLabel:{
type:String,
required:true,
},
},
emits:{
//? update:modelValue event is needed to notify the v-model when the value has changed
['update:modelValue']:null,
select:null,
},
data() {
return {
selectedOption: [],
optionLength:this.size,
}
},
methods: {
},
computed: {
listLength: function(){
return this.list.length;
},
lastElement: function(){
return this.list[this.list.length-1];
},
computedList: function(){
if(Array.isArray(this.list)){
//? the passed data is an array
return this.list;
}else if(typeof(this.list) === 'object' && this.list !== null){
//? the passed data is an object
return Object.keys(this.list);
}else{
console.warn("The passed data is neither an Array or an Object");
return null;
//! the passed data is neither an object or an array
}
}
},
created() {
console.log(this.optionLength);
//? sets the default length of the options to show equal to the number of elements in the list
if(!this.optionLength){
//? if it is an object, then it will take the length of the object keys, otherwise it takes the normal length
this.optionLength = this.computedList.length;
}
},
mounted() {
},
template: `
<p>size:{{optionLength}}</p>
<!-- styling des Selects und dessen Options könnte man noch anpassen -->
<div id="SelectStyle">
<select v-model="selectedOption" class="form-select" :size="this.optionLength" :aria-label="ariaLabel">
<option @click="$emit('update:modelValue', option); $emit('select')" v-for="(option,index) in computedList" :value="option">
<template v-if="typeof(option) === 'object' && option !== null" >
<div class="row " v-for="(element,index) in option"><div class="col">{{index}} : </div><div class="col">{{element}}</div></div>
</template>
<template v-else >
{{option}}
</template>
</option>
</select>
</div>`,
};