feat: avatar upload
This commit is contained in:
parent
c4418676fb
commit
7ccdcf51f2
|
|
@ -0,0 +1,58 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
imageUrl?: string;
|
||||||
|
loading?: boolean;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
imageUrl: "",
|
||||||
|
loading: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="relative">
|
||||||
|
<img
|
||||||
|
v-if="props?.imageUrl"
|
||||||
|
class="aspect-square h-[172px] w-[172px] rounded-full object-cover"
|
||||||
|
:class="{ 'opacity-30': props.loading }"
|
||||||
|
:src="props.imageUrl"
|
||||||
|
alt="avatar"
|
||||||
|
/>
|
||||||
|
<svg
|
||||||
|
v-else
|
||||||
|
:class="{ 'opacity-30': props.loading }"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="172"
|
||||||
|
height="172"
|
||||||
|
viewBox="0 0 172 172"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<mask
|
||||||
|
id="mask0"
|
||||||
|
style="mask-type: alpha"
|
||||||
|
maskUnits="userSpaceOnUse"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="172"
|
||||||
|
height="172"
|
||||||
|
>
|
||||||
|
<circle cx="86" cy="86" r="86" fill="#E0E5EC" />
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#mask0)">
|
||||||
|
<circle cx="86" cy="86" r="86" fill="#E0E5EC" />
|
||||||
|
<path
|
||||||
|
fill="#B1C1CA"
|
||||||
|
d="M101.584 105.423a1.793 1.793 0 0 0-1.57.572 1.834 1.834 0 0 0-.465 1.604c1.019 5.347 4.45 12.685 14.982 17.254 1.248.539 3.176.959 5.621 1.486 9.151 1.977 24.454 5.288 28.214 19.294a1.843 1.843 0 0 0 1.545 1.351 1.84 1.84 0 0 0 1.367-.366 1.846 1.846 0 0 0 .659-1.944c-4.347-16.177-21.685-19.928-31.002-21.941-2.157-.469-4.022-.871-4.934-1.269-6.33-2.743-10.418-6.815-12.19-12.117 17.585 1.305 25.547-5.69 25.898-6.008a1.843 1.843 0 0 0-.325-2.968c-10.148-5.79-10.148-25.795-10.148-33.33 0-21.067-14.21-37.768-32.428-38.03-.173-.006-.347-.01-.52-.011-18.483.103-33.524 16.823-33.524 37.275 0 7.534 0 27.543-10.149 33.329a1.856 1.856 0 0 0-.767 2.35c.121.276.309.519.546.707.51.394 11.773 9.001 25.632 6.387-1.853 5.081-5.886 8.99-12.031 11.657-.89.387-2.663.811-4.716 1.298-9.38 2.227-26.844 6.376-31.216 22.668a1.84 1.84 0 0 0 .185 1.4 1.85 1.85 0 0 0 3.386-.445c3.8-14.176 19.266-17.845 28.502-20.043 2.315-.549 4.143-.984 5.332-1.497 10.532-4.569 13.96-11.907 14.983-17.254a1.83 1.83 0 0 0-.588-1.723 1.833 1.833 0 0 0-1.78-.383c-9.996 3.142-19.232-1.18-23.269-3.577 9.642-8.061 9.642-26.614 9.642-34.874 0-18.427 13.391-33.495 29.987-33.595l.391.022c16.367.233 28.709 14.994 28.709 34.34 0 8.264 0 26.857 9.683 34.918-3.335 1.903-10.939 4.982-23.642 3.463Z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<LoadingSpinner
|
||||||
|
v-if="props.loading"
|
||||||
|
class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div role="status">
|
<div role="status">
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
class="mr-2 h-8 w-8 animate-spin fill-blue-900 text-gray-200 dark:text-gray-600"
|
class="h-8 w-8 animate-spin fill-blue-900 text-gray-200 dark:text-gray-600"
|
||||||
viewBox="0 0 100 101"
|
viewBox="0 0 100 101"
|
||||||
fill="none"
|
fill="none"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,11 @@
|
||||||
import WizardPage from "@/components/onboarding/WizardPage.vue";
|
import WizardPage from "@/components/onboarding/WizardPage.vue";
|
||||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
import { useUserStore } from "@/stores/user";
|
||||||
|
import AvatarImage from "@/components/ui/AvatarImage.vue";
|
||||||
|
import { presignUpload, uploadFile } from "@/services/files";
|
||||||
|
|
||||||
|
const user = useUserStore();
|
||||||
|
|
||||||
const companies = [
|
const companies = [
|
||||||
{ id: 1, name: "Firma 1" },
|
{ id: 1, name: "Firma 1" },
|
||||||
|
|
@ -9,6 +14,28 @@ const companies = [
|
||||||
{ id: 3, name: "Firma 3" },
|
{ id: 3, name: "Firma 3" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const uploadError = ref(false);
|
||||||
|
const avatarLoading = ref(false);
|
||||||
|
|
||||||
|
async function fileSelected(e: Event) {
|
||||||
|
const { files } = e.target as HTMLInputElement;
|
||||||
|
if (!files?.length) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
uploadError.value = false;
|
||||||
|
avatarLoading.value = true;
|
||||||
|
const file = files[0];
|
||||||
|
const presignData = await presignUpload(file);
|
||||||
|
await uploadFile(presignData.pre_sign, file);
|
||||||
|
user.avatar_url = presignData.file_info.url;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
uploadError.value = true;
|
||||||
|
} finally {
|
||||||
|
avatarLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const selectedCompany = ref(companies[0]);
|
const selectedCompany = ref(companies[0]);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -33,39 +60,22 @@ const selectedCompany = ref(companies[0]);
|
||||||
Lade ein Profilbild hoch, damit dich andere Personen auf den ersten Blick
|
Lade ein Profilbild hoch, damit dich andere Personen auf den ersten Blick
|
||||||
erkennen.
|
erkennen.
|
||||||
</p>
|
</p>
|
||||||
<button class="btn-primary flex items-center">
|
<div class="btn-primary relative inline-flex cursor-pointer items-center">
|
||||||
Bild hochladen
|
<input
|
||||||
|
id="upload"
|
||||||
|
type="file"
|
||||||
|
class="absolute opacity-0"
|
||||||
|
accept="image/*"
|
||||||
|
@change="fileSelected"
|
||||||
|
/>
|
||||||
|
{{ $t("a.Bild hochladen") }}
|
||||||
<it-icon-upload class="it-icon ml-2 h-6 w-6" />
|
<it-icon-upload class="it-icon ml-2 h-6 w-6" />
|
||||||
</button>
|
</div>
|
||||||
</div>
|
<p v-if="uploadError" class="mt-3 text-red-700">
|
||||||
<div>
|
{{ $t("a.Datei kann nicht gespeichert werden.") }}
|
||||||
<svg
|
</p>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="172"
|
|
||||||
height="172"
|
|
||||||
viewBox="0 0 172 172"
|
|
||||||
fill="none"
|
|
||||||
>
|
|
||||||
<mask
|
|
||||||
id="mask0"
|
|
||||||
style="mask-type: alpha"
|
|
||||||
maskUnits="userSpaceOnUse"
|
|
||||||
x="0"
|
|
||||||
y="0"
|
|
||||||
width="172"
|
|
||||||
height="172"
|
|
||||||
>
|
|
||||||
<circle cx="86" cy="86" r="86" fill="#E0E5EC" />
|
|
||||||
</mask>
|
|
||||||
<g mask="url(#mask0)">
|
|
||||||
<circle cx="86" cy="86" r="86" fill="#E0E5EC" />
|
|
||||||
<path
|
|
||||||
fill="#B1C1CA"
|
|
||||||
d="M101.584 105.423a1.793 1.793 0 0 0-1.57.572 1.834 1.834 0 0 0-.465 1.604c1.019 5.347 4.45 12.685 14.982 17.254 1.248.539 3.176.959 5.621 1.486 9.151 1.977 24.454 5.288 28.214 19.294a1.843 1.843 0 0 0 1.545 1.351 1.84 1.84 0 0 0 1.367-.366 1.846 1.846 0 0 0 .659-1.944c-4.347-16.177-21.685-19.928-31.002-21.941-2.157-.469-4.022-.871-4.934-1.269-6.33-2.743-10.418-6.815-12.19-12.117 17.585 1.305 25.547-5.69 25.898-6.008a1.843 1.843 0 0 0-.325-2.968c-10.148-5.79-10.148-25.795-10.148-33.33 0-21.067-14.21-37.768-32.428-38.03-.173-.006-.347-.01-.52-.011-18.483.103-33.524 16.823-33.524 37.275 0 7.534 0 27.543-10.149 33.329a1.856 1.856 0 0 0-.767 2.35c.121.276.309.519.546.707.51.394 11.773 9.001 25.632 6.387-1.853 5.081-5.886 8.99-12.031 11.657-.89.387-2.663.811-4.716 1.298-9.38 2.227-26.844 6.376-31.216 22.668a1.84 1.84 0 0 0 .185 1.4 1.85 1.85 0 0 0 3.386-.445c3.8-14.176 19.266-17.845 28.502-20.043 2.315-.549 4.143-.984 5.332-1.497 10.532-4.569 13.96-11.907 14.983-17.254a1.83 1.83 0 0 0-.588-1.723 1.833 1.833 0 0 0-1.78-.383c-9.996 3.142-19.232-1.18-23.269-3.577 9.642-8.061 9.642-26.614 9.642-34.874 0-18.427 13.391-33.495 29.987-33.595l.391.022c16.367.233 28.709 14.994 28.709 34.34 0 8.264 0 26.857 9.683 34.918-3.335 1.903-10.939 4.982-23.642 3.463Z"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
|
<AvatarImage :loading="avatarLoading" :image-url="user.avatar_url" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue