Add more editable profile fields
This commit is contained in:
parent
47896444a6
commit
d56c346512
|
|
@ -3,6 +3,8 @@ import { useEntities } from "@/services/entities";
|
|||
import AvatarImage from "@/components/ui/AvatarImage.vue";
|
||||
import { ref } from "vue";
|
||||
import { type User, useUserStore } from "@/stores/user";
|
||||
import ItDatePicker from "@/components/ui/ItDatePicker.vue";
|
||||
import { normalizeSwissPhoneNumber } from "@/utils/phone";
|
||||
|
||||
const emit = defineEmits(["cancel", "save"]);
|
||||
|
||||
|
|
@ -26,6 +28,7 @@ const formData = ref({
|
|||
birth_date: user.birth_date,
|
||||
|
||||
organisation: user.organisation,
|
||||
organisation_detail_name: user.organisation_detail_name,
|
||||
organisation_street: user.organisation_street,
|
||||
organisation_street_number: user.organisation_street_number,
|
||||
organisation_postal_code: user.organisation_postal_code,
|
||||
|
|
@ -35,7 +38,8 @@ const formData = ref({
|
|||
});
|
||||
|
||||
async function save() {
|
||||
const { country_code, organisation_country_code, ...profileData } = formData.value;
|
||||
const { country_code, organisation_country_code, phone_number, ...profileData } =
|
||||
formData.value;
|
||||
const typedProfileData: Partial<User> = { ...profileData };
|
||||
|
||||
typedProfileData.country = countries.value.find(
|
||||
|
|
@ -45,6 +49,10 @@ async function save() {
|
|||
(c) => c.country_code === organisation_country_code
|
||||
);
|
||||
|
||||
if (phone_number) {
|
||||
typedProfileData.phone_number = normalizeSwissPhoneNumber(phone_number);
|
||||
}
|
||||
|
||||
await user.updateUserProfile(typedProfileData);
|
||||
emit("save");
|
||||
}
|
||||
|
|
@ -130,6 +138,28 @@ async function avatarUpload(e: Event) {
|
|||
disabled
|
||||
class="disabled:bg-gray-50 mb-4 block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 disabled:cursor-not-allowed disabled:text-gray-500 disabled:ring-gray-200 sm:max-w-sm sm:text-sm sm:leading-6"
|
||||
/>
|
||||
|
||||
<label for="phone" class="block pb-1.5 leading-6">
|
||||
{{ $t("a.Telefonnummer") }}
|
||||
</label>
|
||||
<div>
|
||||
<input
|
||||
id="phone"
|
||||
v-model="formData.phone_number"
|
||||
type="text"
|
||||
name="phone"
|
||||
autocomplete="phone-number"
|
||||
class="disabled:bg-gray-50 mb-4 block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 disabled:cursor-not-allowed disabled:text-gray-500 disabled:ring-gray-200 sm:max-w-sm sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label for="birth-date" class="block pb-1.5 leading-6">
|
||||
{{ $t("a.Geburtsdatum") }}
|
||||
</label>
|
||||
<div class="mb-4 block w-full py-1.5 sm:max-w-sm sm:text-sm sm:leading-6">
|
||||
<ItDatePicker v-model="formData.birth_date"></ItDatePicker>
|
||||
</div>
|
||||
|
||||
<label class="block pb-1.5 leading-6">
|
||||
{{ $t("a.Profilbild") }}
|
||||
</label>
|
||||
|
|
@ -268,6 +298,22 @@ async function avatarUpload(e: Event) {
|
|||
{{ $t("a.Firmenanschrift") }}
|
||||
</h4>
|
||||
|
||||
<div class="flex flex-col justify-start md:flex-row md:space-x-4">
|
||||
<div class="w-full md:max-w-lg">
|
||||
<label for="org-street-address" class="block pb-1.5 leading-6">
|
||||
{{ $t("a.Name") }}
|
||||
</label>
|
||||
|
||||
<input
|
||||
id="org-detail-name"
|
||||
v-model="formData.organisation_detail_name"
|
||||
type="text"
|
||||
name="org-detail-name"
|
||||
class="disabled:bg-gray-50 mb-4 block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 disabled:cursor-not-allowed disabled:text-gray-500 disabled:ring-gray-200 sm:text-sm sm:leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-start md:flex-row md:space-x-4">
|
||||
<div class="w-full md:max-w-sm">
|
||||
<label for="org-street-address" class="block pb-1.5 leading-6">
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import { useUserStore } from "@/stores/user";
|
|||
import { computed } from "vue";
|
||||
import { useEntities } from "@/services/entities";
|
||||
import { useTranslation } from "i18next-vue";
|
||||
import dayjs from "dayjs";
|
||||
import { displaySwissPhoneNumber } from "@/utils/phone";
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
|
@ -10,21 +12,20 @@ const user = useUserStore();
|
|||
const { organisations } = useEntities();
|
||||
|
||||
const privateAddress = computed(() => {
|
||||
let addressText = `${user.street} ${user.street_number}`.trim();
|
||||
if (user.postal_code || user.city) {
|
||||
if (addressText.length) {
|
||||
addressText += ", ";
|
||||
}
|
||||
addressText += `${user.postal_code} ${user.city}`;
|
||||
}
|
||||
if (user.country) {
|
||||
if (addressText.length) {
|
||||
addressText += ", ";
|
||||
}
|
||||
addressText += user.country.name;
|
||||
const textParts = [];
|
||||
|
||||
if (user.street || user.street_number) {
|
||||
textParts.push(`${user.street} ${user.street_number}`.trim());
|
||||
}
|
||||
|
||||
return addressText.trim();
|
||||
if (user.postal_code || user.city) {
|
||||
textParts.push(`${user.postal_code} ${user.city}`);
|
||||
}
|
||||
if (textParts.length && user.country) {
|
||||
textParts.push(user.country.name);
|
||||
}
|
||||
|
||||
return textParts;
|
||||
});
|
||||
|
||||
const organisationName = computed(() => {
|
||||
|
|
@ -36,22 +37,25 @@ const organisationName = computed(() => {
|
|||
});
|
||||
|
||||
const orgAddress = computed(() => {
|
||||
let addressText =
|
||||
`${user.organisation_street} ${user.organisation_street_number}`.trim();
|
||||
if (user.organisation_postal_code || user.organisation_city) {
|
||||
if (addressText.length) {
|
||||
addressText += ", ";
|
||||
}
|
||||
addressText += `${user.organisation_postal_code} ${user.organisation_city}`;
|
||||
}
|
||||
if (user.organisation_country) {
|
||||
if (addressText.length) {
|
||||
addressText += ", ";
|
||||
}
|
||||
addressText += user.organisation_country.name;
|
||||
const textParts = [];
|
||||
|
||||
if (user.organisation_detail_name) {
|
||||
textParts.push(user.organisation_detail_name);
|
||||
}
|
||||
|
||||
return addressText.trim();
|
||||
if (user.organisation_street || user.organisation_street_number) {
|
||||
textParts.push(
|
||||
`${user.organisation_street} ${user.organisation_street_number}`.trim()
|
||||
);
|
||||
}
|
||||
if (user.organisation_postal_code || user.organisation_city) {
|
||||
textParts.push(`${user.organisation_postal_code} ${user.organisation_city}`);
|
||||
}
|
||||
if (textParts.length && user.organisation_country) {
|
||||
textParts.push(user.organisation_country.name);
|
||||
}
|
||||
|
||||
return textParts;
|
||||
});
|
||||
|
||||
const invoiceAddress = computed(() => {
|
||||
|
|
@ -74,13 +78,34 @@ const invoiceAddress = computed(() => {
|
|||
{{ $t("a.E-Mail Adresse") }}
|
||||
</label>
|
||||
<div class="mb-3 sm:col-span-2 sm:mb-0">{{ user.email }}</div>
|
||||
<label class="block font-semibold leading-6">
|
||||
{{ $t("a.Telefonnummer") }}
|
||||
</label>
|
||||
<div class="mb-3 sm:col-span-2 sm:mb-0">
|
||||
<span v-if="user.phone_number">
|
||||
{{ displaySwissPhoneNumber(user.phone_number) }}
|
||||
</span>
|
||||
<span v-else class="text-gray-800">{{ $t("a.Keine Angabe") }}</span>
|
||||
</div>
|
||||
<label class="block font-semibold leading-6">
|
||||
{{ $t("a.Geburtsdatum") }}
|
||||
</label>
|
||||
<div class="mb-3 sm:col-span-2 sm:mb-0">
|
||||
<span v-if="user.birth_date">
|
||||
{{ dayjs(user.birth_date).format("DD.MM.YYYY") }}
|
||||
</span>
|
||||
<span v-else class="text-gray-800">{{ $t("a.Keine Angabe") }}</span>
|
||||
</div>
|
||||
<label class="block font-semibold leading-6">
|
||||
{{ $t("a.Privatadresse") }}
|
||||
</label>
|
||||
<div class="mb-3 sm:col-span-2 sm:mb-0">
|
||||
<template v-if="privateAddress">
|
||||
{{ privateAddress }}
|
||||
</template>
|
||||
<div v-if="privateAddress.length">
|
||||
<span v-for="(line, index) in privateAddress" :key="index">
|
||||
{{ line }}
|
||||
<br />
|
||||
</span>
|
||||
</div>
|
||||
<span v-else class="text-gray-800">{{ $t("a.Keine Angabe") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -94,9 +119,13 @@ const invoiceAddress = computed(() => {
|
|||
{{ $t("a.Firmenanschrift") }}
|
||||
</label>
|
||||
<div class="sm:col-span-2">
|
||||
<template v-if="orgAddress">
|
||||
{{ orgAddress }}
|
||||
</template>
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div v-if="orgAddress">
|
||||
<span v-for="(line, index) in orgAddress" :key="index">
|
||||
{{ line }}
|
||||
<br />
|
||||
</span>
|
||||
</div>
|
||||
<span v-else class="text-gray-800">{{ $t("a.Keine Angabe") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import VueDatePicker from "@vuepic/vue-datepicker";
|
||||
import "@vuepic/vue-datepicker/dist/main.css";
|
||||
import { defineProps, withDefaults, defineModel } from "vue";
|
||||
|
||||
const model = defineModel<string>();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import VerticalBarChart from "@/components/ui/VerticalBarChart.vue";
|
|||
import LearningPathCircle from "@/pages/learningPath/learningPathPage/LearningPathCircle.vue";
|
||||
import logger from "loglevel";
|
||||
import { reactive, ref } from "vue";
|
||||
import VueDatePicker from "@vuepic/vue-datepicker";
|
||||
import "@vuepic/vue-datepicker/dist/main.css";
|
||||
|
||||
const state = reactive({
|
||||
checkboxValue: true,
|
||||
|
|
@ -34,6 +36,8 @@ const state = reactive({
|
|||
},
|
||||
});
|
||||
|
||||
const birtDate = ref("1982-06-15");
|
||||
|
||||
const dropdownData = [
|
||||
{
|
||||
title: "Option 1",
|
||||
|
|
@ -411,6 +415,11 @@ function log(data: any) {
|
|||
></ItDropdownSelect>
|
||||
{{ state.dropdownSelected }}
|
||||
|
||||
<h2 class="mb-8 mt-8">Date Picker</h2>
|
||||
<div class="mt-2">
|
||||
<VueDatePicker v-model="birthDate"></VueDatePicker>
|
||||
</div>
|
||||
|
||||
<h2 class="mb-8 mt-8">Checkbox</h2>
|
||||
|
||||
<ItCheckbox
|
||||
|
|
|
|||
|
|
@ -114,8 +114,9 @@ class User(AbstractUser):
|
|||
blank=True,
|
||||
)
|
||||
|
||||
# fields gathered from cembra pay form
|
||||
birth_date = models.DateField(null=True, blank=True)
|
||||
|
||||
# phone number should be stored in the format +41792018586 (not validated)
|
||||
phone_number = models.CharField(max_length=255, blank=True, default="")
|
||||
|
||||
# is only set by abacus invoice export code
|
||||
|
|
|
|||
Loading…
Reference in New Issue