71 lines
1.8 KiB
Vue
71 lines
1.8 KiB
Vue
<script lang="ts" setup>
|
|
import { useHttp } from '@inertiajs/vue3';
|
|
import { ref, watch } from 'vue';
|
|
import InputError from '@/components/InputError.vue';
|
|
import { Label } from '@/components/ui/label';
|
|
import { Input } from '@/components/ui/input';
|
|
import { nameToSlug } from '@/routes/teams';
|
|
import type {
|
|
TeamSlugProps,
|
|
TeamSlugRequest,
|
|
TeamSlugResponse,
|
|
} from '@/types/team';
|
|
|
|
const props = defineProps<TeamSlugProps>();
|
|
const slug = defineModel<string>('slug', { required: true });
|
|
const slugTaken = defineModel<boolean>('slugTaken', { required: true });
|
|
const previewError = ref('');
|
|
const http = useHttp<TeamSlugRequest, TeamSlugResponse>({
|
|
name: '',
|
|
ignored_slug: null,
|
|
});
|
|
|
|
watch(
|
|
() => props.name,
|
|
(name, _previous, onCleanup) => {
|
|
let active = true;
|
|
slugTaken.value = false;
|
|
previewError.value = '';
|
|
|
|
const timer = setTimeout(async () => {
|
|
if (!name.trim()) {
|
|
slug.value = '';
|
|
return;
|
|
}
|
|
|
|
http.name = name;
|
|
http.ignored_slug = props.ignoredSlug ?? null;
|
|
|
|
try {
|
|
const response = await http.submit(nameToSlug());
|
|
if (active) {
|
|
slug.value = response.slug;
|
|
slugTaken.value = response.taken;
|
|
previewError.value = response.taken
|
|
? 'Der Slug ist bereits vergeben.'
|
|
: '';
|
|
}
|
|
} catch {
|
|
if (active) {
|
|
previewError.value = 'Die Slug-Vorschau konnte nicht geladen werden.';
|
|
}
|
|
}
|
|
}, 250);
|
|
|
|
onCleanup(() => {
|
|
active = false;
|
|
clearTimeout(timer);
|
|
http.cancel();
|
|
});
|
|
},
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<div class="grid items-start gap-3">
|
|
<Label for="slug">Slug</Label>
|
|
<Input id="slug" :model-value="slug" disabled name="slug" />
|
|
<InputError :message="error || previewError" />
|
|
</div>
|
|
</template>
|