Progressing on profile edition and thumbnail cropping

This commit is contained in:
2024-09-11 17:47:04 +02:00
parent e904f28b3b
commit 6856d3b9af
25 changed files with 278 additions and 88 deletions

View File

@@ -0,0 +1,41 @@
<template>
<Teleport to="#teleports" v-if="visible">
<div @click.self="() => !focused && hide()" class="z-[100] absolute top-0 bottom-0 left-0 right-0 bg-light-0 dark:bg-dark-0 !bg-opacity-80 flex justify-center items-center">
<div class="relative border border-light-35 dark:border-dark-35 bg-light-0 dark:bg-dark-0 min-h-40 min-w-72">
<span v-if="closeIcon" class="cursor-pointer absolute top-1 right-1 flex hover:opacity-75" @click="() => hide()"><Icon :width="20" :height="20" icon="icons/close" /></span>
<div class="p-6" :class="$attrs.class">
<slot></slot>
</div>
</div>
</div>
</Teleport>
</template>
<script setup lang="ts">
const props = defineProps({
focused: {
type: Boolean,
defualt: false,
},
closeIcon: {
type: Boolean,
default: true,
}
})
const emit = defineEmits(['show', 'hide']);
const visible = ref(false);
function show()
{
visible.value = true;
emit('show');
}
function hide()
{
visible.value = false;
emit('hide');
}
defineExpose({hide, show});
</script>

View File

@@ -1,11 +1,11 @@
<template>
<Teleport to="#teleports">
<div v-show="display" :class="$attrs.class" class="absolute border-2 border-light-35 dark:border-dark-35 max-w-[550px] max-h-[450px] bg-light-0 dark:bg-dark-0 text-light-100 dark:text-dark-100" :style="pos"
<Teleport to="#teleports" v-if="display">
<div class="absolute border-2 border-light-35 dark:border-dark-35 max-w-[550px] max-h-[450px] bg-light-0 dark:bg-dark-0 text-light-100 dark:text-dark-100 overflow-hidden" :style="pos"
@mouseenter="debounce(show, 250)" @mouseleave="debounce(() => { emit('beforeHide'); display = false }, 250)">
<slot name="content"></slot>
</div>
</Teleport>
<span ref="el" @mouseenter="debounce(show, 250)" @mouseleave="debounce(() => { emit('beforeHide'); display = false }, 250)">
<span ref="el" :class="$attrs.class" @mouseenter="debounce(show, 250)" @mouseleave="debounce(() => { emit('beforeHide'); display = false }, 250)">
<slot name="default"></slot>
</span>
</template>

View File

@@ -13,11 +13,9 @@ watchEffect(() => err.value = props.error);
</script>
<template>
<template></template>
<div class="m-1">
<div class="m-1 flex justify-between items-center gap-8">
<label v-if="title" class="pe-4">{{ title }}</label>
<Input @input="err = false" :class="{ 'input-has-error': !!err }" v-model="model"
v-bind="$attrs" />
<span v-if="err && typeof err === 'string'" class="text-light-red dark:text-dark-red block pb-2">{{ err }}</span>
<Input class="flex-1" @input="err = false" :class="{ 'input-has-error': !!err }" v-model="model" v-bind="$attrs" />
</div>
<span v-if="err && typeof err === 'string'" class="text-light-red dark:text-dark-red block pb-2">{{ err }}</span>
</template>

View File

@@ -58,10 +58,9 @@ onUnmounted(() => {
<ThemeSwitch />
<NuxtLink @click="hideNavigation" class="" :to="{ path: '/user/profile', force: true }"><div class=" hover:border-opacity-70 flex border p-px border-light-70 dark:border-dark-70">
<Icon v-if="!loggedIn" icon="icons/user-login" :width=28 :height=28 />
<picture v-else :width=28 :height=28 class="flex" >
<source :src="`/users/${user?.id}/small.jpg`" :width=28 :height=28 />
<Icon :icon="`users/unknown`" :width=28 :height=28 ></Icon>
</picture>
<Picture v-else :src="`/users/${user?.id}/small.jpg`" :width=28 :height=28 class="flex" >
<Icon :icon="`icons/unknown`" :width=28 :height=28 ></Icon>
</Picture>
</div></NuxtLink>
</div>
</div>

View File

@@ -0,0 +1,31 @@
<template>
<span>
<img v-show="src && !fallback" @load="hideFallback" @error="showFallback" :src="src" :width="width" :height="height" />
<span v-show="!src || fallback"><slot></slot></span>
</span>
</template>
<script setup lang="ts">
const props = defineProps({
src: {
type: String,
},
width: {
type: Number,
},
height: {
type: Number,
}
});
const fallback = ref(false);
const showFallback = () => toggleFallback(true);
const hideFallback = () => toggleFallback(false);
function toggleFallback(toggle: boolean): void
{
console.log("Something happened")
fallback.value = toggle;
}
</script>

View File

@@ -0,0 +1,27 @@
<template>
<label>
<slot></slot>
<input ref="input" :accept="accept" :multiple="multiple" type="file" class="hidden" @change.self="(e) => files = [...(e.target as HTMLInputElement)?.files ?? []]"/>
</label>
</template>
<script setup lang="ts">
const props = defineProps({
accept: {
type: String,
},
multiple: {
type: Boolean,
default: false,
}
});
const input = useTemplateRef('input');
const files = ref<File[]>([]);
watch([files], () => emit('change', files.value));
const emit = defineEmits(['change']);
defineExpose({ files });
</script>