@@ -14,6 +14,9 @@
|
||||
<Variant title="cancelled">
|
||||
<EventCard :event="cancelledEvent" />
|
||||
</Variant>
|
||||
<Variant title="Row mode">
|
||||
<EventCard :event="longEvent" mode="row" />
|
||||
</Variant>
|
||||
</Story>
|
||||
</template>
|
||||
|
||||
@@ -53,8 +56,8 @@ const baseEvent: IEvent = {
|
||||
uuid: "",
|
||||
title: "A very interesting event",
|
||||
description: "Things happen",
|
||||
beginsOn: new Date(),
|
||||
endsOn: new Date(),
|
||||
beginsOn: new Date().toISOString(),
|
||||
endsOn: new Date().toISOString(),
|
||||
physicalAddress: {
|
||||
description: "Somewhere",
|
||||
street: "",
|
||||
@@ -74,7 +77,7 @@ const baseEvent: IEvent = {
|
||||
url: "",
|
||||
local: true,
|
||||
slug: "",
|
||||
publishAt: new Date(),
|
||||
publishAt: new Date().toISOString(),
|
||||
status: EventStatus.CONFIRMED,
|
||||
visibility: EventVisibility.PUBLIC,
|
||||
joinOptions: EventJoinOptions.FREE,
|
||||
@@ -130,7 +133,7 @@ const event = reactive<IEvent>(baseEvent);
|
||||
const longEvent = reactive<IEvent>({
|
||||
...baseEvent,
|
||||
title:
|
||||
"A very long title that will have trouble to display because it will take multiple lines but where will it stop ?! Maybe after 3 lines is enough. Let's say so.",
|
||||
"A very long title that will have trouble to display because it will take multiple lines but where will it stop ?! Maybe after 3 lines is enough. Let's say so. But if it doesn't work, we really need to truncate it at some point. Definitively.",
|
||||
});
|
||||
|
||||
const tentativeEvent = reactive<IEvent>({
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
<template>
|
||||
<router-link
|
||||
class="mbz-card max-w-xs shrink-0 w-[18rem] snap-center dark:bg-mbz-purple"
|
||||
:to="{ name: RouteName.EVENT, params: { uuid: event.uuid } }"
|
||||
<LinkOrRouterLink
|
||||
class="mbz-card snap-center dark:bg-mbz-purple"
|
||||
:class="{
|
||||
'sm:flex sm:items-start': mode === 'row',
|
||||
'max-w-xs w-[18rem] shrink-0 flex flex-col': mode === 'column',
|
||||
}"
|
||||
:to="to"
|
||||
:isInternal="isInternal"
|
||||
>
|
||||
<div class="bg-secondary rounded-lg">
|
||||
<div
|
||||
class="bg-secondary rounded-lg"
|
||||
:class="{ 'sm:w-full sm:max-w-[20rem]': mode === 'row' }"
|
||||
>
|
||||
<figure class="block relative pt-40">
|
||||
<lazy-image-wrapper
|
||||
:picture="event.picture"
|
||||
style="height: 100%; position: absolute; top: 0; left: 0; width: 100%"
|
||||
/>
|
||||
<div
|
||||
class="absolute top-3 right-0 ltr:-mr-1 rtl:-ml-1 z-10 max-w-xs no-underline flex flex-col gap-1"
|
||||
class="absolute top-3 right-0 ltr:-mr-1 rtl:-ml-1 z-10 max-w-xs no-underline flex flex-col gap-1 items-end"
|
||||
v-show="mode === 'column'"
|
||||
v-if="event.tags || event.status !== EventStatus.CONFIRMED"
|
||||
>
|
||||
<mobilizon-tag
|
||||
@@ -30,30 +39,39 @@
|
||||
v-for="tag in (event.tags || []).slice(0, 3)"
|
||||
:key="tag.slug"
|
||||
>
|
||||
<mobilizon-tag dir="auto">{{ tag.title }}</mobilizon-tag>
|
||||
<mobilizon-tag dir="auto" :with-hash-tag="true">{{
|
||||
tag.title
|
||||
}}</mobilizon-tag>
|
||||
</router-link>
|
||||
</div>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="p-2">
|
||||
<div class="p-2 flex-auto" :class="{ 'sm:flex-1': mode === 'row' }">
|
||||
<div class="relative flex flex-col h-full">
|
||||
<div class="-mt-3 h-0 flex mb-3 ltr:ml-0 rtl:mr-0 items-end self-start">
|
||||
<div
|
||||
class="-mt-3 h-0 flex mb-3 ltr:ml-0 rtl:mr-0 items-end self-start"
|
||||
:class="{ 'sm:hidden': mode === 'row' }"
|
||||
>
|
||||
<date-calendar-icon
|
||||
:small="true"
|
||||
v-if="!mergedOptions.hideDate"
|
||||
:date="event.beginsOn.toString()"
|
||||
/>
|
||||
</div>
|
||||
<div class="w-full flex flex-col justify-between">
|
||||
<h3
|
||||
class="text-lg leading-5 line-clamp-3 font-bold text-violet-3 dark:text-white"
|
||||
:title="event.title"
|
||||
<span
|
||||
class="text-gray-700 dark:text-white font-semibold hidden"
|
||||
:class="{ 'sm:block': mode === 'row' }"
|
||||
>{{ formatDateTimeWithCurrentLocale }}</span
|
||||
>
|
||||
<div class="w-full flex flex-col justify-between h-full">
|
||||
<h2
|
||||
class="mt-0 mb-2 text-2xl line-clamp-3 font-bold text-violet-3 dark:text-white"
|
||||
dir="auto"
|
||||
:lang="event.language"
|
||||
>
|
||||
{{ event.title }}
|
||||
</h3>
|
||||
<div class="pt-3">
|
||||
</h2>
|
||||
<div class="">
|
||||
<div
|
||||
class="flex items-center text-violet-3 dark:text-white"
|
||||
dir="auto"
|
||||
@@ -68,7 +86,7 @@
|
||||
/>
|
||||
</figure>
|
||||
<account-circle v-else />
|
||||
<span class="text-sm font-semibold ltr:pl-2 rtl:pr-2">
|
||||
<span class="font-semibold ltr:pl-2 rtl:pr-2">
|
||||
{{ organizerDisplayName(event) }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -84,11 +102,38 @@
|
||||
<Video />
|
||||
<span class="ltr:pl-2 rtl:pr-2">{{ $t("Online") }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="mt-1 no-underline gap-1 items-center hidden"
|
||||
:class="{ 'sm:flex': mode === 'row' }"
|
||||
v-if="event.tags || event.status !== EventStatus.CONFIRMED"
|
||||
>
|
||||
<mobilizon-tag
|
||||
variant="info"
|
||||
v-if="event.status === EventStatus.TENTATIVE"
|
||||
>
|
||||
{{ $t("Tentative") }}
|
||||
</mobilizon-tag>
|
||||
<mobilizon-tag
|
||||
variant="danger"
|
||||
v-if="event.status === EventStatus.CANCELLED"
|
||||
>
|
||||
{{ $t("Cancelled") }}
|
||||
</mobilizon-tag>
|
||||
<router-link
|
||||
:to="{ name: RouteName.TAG, params: { tag: tag.title } }"
|
||||
v-for="tag in (event.tags || []).slice(0, 3)"
|
||||
:key="tag.slug"
|
||||
>
|
||||
<mobilizon-tag :with-hash-tag="true" dir="auto">{{
|
||||
tag.title
|
||||
}}</mobilizon-tag>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</router-link>
|
||||
</LinkOrRouterLink>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -104,17 +149,29 @@ import { EventStatus } from "@/types/enums";
|
||||
import RouteName from "../../router/name";
|
||||
import InlineAddress from "@/components/Address/InlineAddress.vue";
|
||||
|
||||
import { computed } from "vue";
|
||||
import MobilizonTag from "../Tag.vue";
|
||||
import { computed, inject } from "vue";
|
||||
import MobilizonTag from "@/components/Tag.vue";
|
||||
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
|
||||
import Video from "vue-material-design-icons/Video.vue";
|
||||
import { formatDateTimeForEvent } from "@/utils/datetime";
|
||||
import type { Locale } from "date-fns";
|
||||
import LinkOrRouterLink from "../core/LinkOrRouterLink.vue";
|
||||
|
||||
const props = defineProps<{ event: IEvent; options?: IEventCardOptions }>();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
event: IEvent;
|
||||
options?: IEventCardOptions;
|
||||
mode?: "row" | "column";
|
||||
}>(),
|
||||
{ mode: "column" }
|
||||
);
|
||||
const defaultOptions: IEventCardOptions = {
|
||||
hideDate: false,
|
||||
loggedPerson: false,
|
||||
hideDetails: false,
|
||||
organizerActor: null,
|
||||
isRemoteEvent: false,
|
||||
isLoggedIn: true,
|
||||
};
|
||||
|
||||
const mergedOptions = computed<IEventCardOptions>(() => ({
|
||||
@@ -132,4 +189,31 @@ const mergedOptions = computed<IEventCardOptions>(() => ({
|
||||
const actorAvatarURL = computed<string | null>(() =>
|
||||
organizerAvatarUrl(props.event)
|
||||
);
|
||||
|
||||
const dateFnsLocale = inject<Locale>("dateFnsLocale");
|
||||
|
||||
const formatDateTimeWithCurrentLocale = computed(() => {
|
||||
if (!dateFnsLocale) return;
|
||||
return formatDateTimeForEvent(new Date(props.event.beginsOn), dateFnsLocale);
|
||||
});
|
||||
|
||||
const isInternal = computed(() => {
|
||||
return (
|
||||
mergedOptions.value.isRemoteEvent &&
|
||||
mergedOptions.value.isLoggedIn === false
|
||||
);
|
||||
});
|
||||
|
||||
const to = computed(() => {
|
||||
if (mergedOptions.value.isRemoteEvent) {
|
||||
if (mergedOptions.value.isLoggedIn === false) {
|
||||
return props.event.url;
|
||||
}
|
||||
return {
|
||||
name: RouteName.INTERACT,
|
||||
query: { uri: encodeURI(props.event.url) },
|
||||
};
|
||||
}
|
||||
return { name: RouteName.EVENT, params: { uuid: props.event.uuid } };
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</p>
|
||||
<p v-else-if="isSameDay() && showStartTime && showEndTime">
|
||||
<span>{{
|
||||
$t("On {date} from {startTime} to {endTime}", {
|
||||
t("On {date} from {startTime} to {endTime}", {
|
||||
date: formatDate(beginsOn),
|
||||
startTime: formatTime(beginsOn, timezoneToShow),
|
||||
endTime: formatTime(endsOn, timezoneToShow),
|
||||
@@ -31,27 +31,24 @@
|
||||
</p>
|
||||
<p v-else-if="isSameDay() && showStartTime && !showEndTime">
|
||||
{{
|
||||
$t("On {date} starting at {startTime}", {
|
||||
t("On {date} starting at {startTime}", {
|
||||
date: formatDate(beginsOn),
|
||||
startTime: formatTime(beginsOn),
|
||||
})
|
||||
}}
|
||||
</p>
|
||||
<p v-else-if="isSameDay()">
|
||||
{{ $t("On {date}", { date: formatDate(beginsOn) }) }}
|
||||
{{ t("On {date}", { date: formatDate(beginsOn) }) }}
|
||||
</p>
|
||||
<p v-else-if="endsOn && showStartTime && showEndTime">
|
||||
<span>
|
||||
{{
|
||||
$t(
|
||||
"From the {startDate} at {startTime} to the {endDate} at {endTime}",
|
||||
{
|
||||
startDate: formatDate(beginsOn),
|
||||
startTime: formatTime(beginsOn, timezoneToShow),
|
||||
endDate: formatDate(endsOn),
|
||||
endTime: formatTime(endsOn, timezoneToShow),
|
||||
}
|
||||
)
|
||||
t("From the {startDate} at {startTime} to the {endDate} at {endTime}", {
|
||||
startDate: formatDate(beginsOn),
|
||||
startTime: formatTime(beginsOn, timezoneToShow),
|
||||
endDate: formatDate(endsOn),
|
||||
endTime: formatTime(endsOn, timezoneToShow),
|
||||
})
|
||||
}}
|
||||
</span>
|
||||
<br />
|
||||
@@ -66,7 +63,7 @@
|
||||
<p v-else-if="endsOn && showStartTime">
|
||||
<span>
|
||||
{{
|
||||
$t("From the {startDate} at {startTime} to the {endDate}", {
|
||||
t("From the {startDate} at {startTime} to the {endDate}", {
|
||||
startDate: formatDate(beginsOn),
|
||||
startTime: formatTime(beginsOn, timezoneToShow),
|
||||
endDate: formatDate(endsOn),
|
||||
@@ -169,22 +166,22 @@ const differentFromUserTimezone = computed((): boolean => {
|
||||
const singleTimeZone = computed((): string => {
|
||||
if (showLocalTimezone.value) {
|
||||
return t("Local time ({timezone})", {
|
||||
timezone: timezoneToShow,
|
||||
}) as string;
|
||||
timezone: timezoneToShow.value,
|
||||
});
|
||||
}
|
||||
return t("Time in your timezone ({timezone})", {
|
||||
timezone: timezoneToShow,
|
||||
}) as string;
|
||||
timezone: timezoneToShow.value,
|
||||
});
|
||||
});
|
||||
|
||||
const multipleTimeZones = computed((): string => {
|
||||
if (showLocalTimezone.value) {
|
||||
return t("Local time ({timezone})", {
|
||||
timezone: timezoneToShow,
|
||||
}) as string;
|
||||
return t("Local times ({timezone})", {
|
||||
timezone: timezoneToShow.value,
|
||||
});
|
||||
}
|
||||
return t("Times in your timezone ({timezone})", {
|
||||
timezone: timezoneToShow,
|
||||
}) as string;
|
||||
timezone: timezoneToShow.value,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -87,7 +87,7 @@ const RoutingParamType = {
|
||||
},
|
||||
};
|
||||
|
||||
const MapLeaflet = import("../../components/Map.vue");
|
||||
const MapLeaflet = import("@/components/LeafletMap.vue");
|
||||
|
||||
const props = defineProps<{
|
||||
address: IAddress;
|
||||
|
||||
@@ -136,10 +136,10 @@ const metadata = computed({
|
||||
};
|
||||
}) as any[];
|
||||
},
|
||||
set(metadata: IEventMetadataDescription[]) {
|
||||
set(newMetadata: IEventMetadataDescription[]) {
|
||||
emit(
|
||||
"update:modelValue",
|
||||
metadata.filter((elem) => elem)
|
||||
newMetadata.filter((elem) => elem)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="address" v-if="physicalAddress">
|
||||
<address-info :address="physicalAddress" />
|
||||
<o-button
|
||||
type="is-text"
|
||||
variant="text"
|
||||
class="map-show-button"
|
||||
@click="$emit('showMapModal', true)"
|
||||
v-if="physicalAddress.geom"
|
||||
|
||||
@@ -22,27 +22,23 @@
|
||||
:lang="event.language"
|
||||
dir="auto"
|
||||
>
|
||||
<b-tag
|
||||
<tag
|
||||
variant="info"
|
||||
class="mr-1"
|
||||
v-if="event.status === EventStatus.TENTATIVE"
|
||||
>
|
||||
{{ $t("Tentative") }}
|
||||
</b-tag>
|
||||
<b-tag
|
||||
</tag>
|
||||
<tag
|
||||
variant="danger"
|
||||
class="mr-1"
|
||||
v-if="event.status === EventStatus.CANCELLED"
|
||||
>
|
||||
{{ $t("Cancelled") }}
|
||||
</b-tag>
|
||||
<b-tag
|
||||
class="mr-2"
|
||||
variant="warning"
|
||||
size="is-medium"
|
||||
v-if="event.draft"
|
||||
>{{ $t("Draft") }}</b-tag
|
||||
>
|
||||
</tag>
|
||||
<tag class="mr-2" variant="warning" size="medium" v-if="event.draft">{{
|
||||
$t("Draft")
|
||||
}}</tag>
|
||||
{{ event.title }}
|
||||
</h3>
|
||||
<inline-address
|
||||
@@ -99,7 +95,7 @@
|
||||
</span>
|
||||
<span v-if="event.participantStats.notApproved > 0">
|
||||
<o-button
|
||||
type="is-text"
|
||||
variant="text"
|
||||
@click="
|
||||
gotToWithCheck(participation, {
|
||||
name: RouteName.PARTICIPATIONS,
|
||||
@@ -134,6 +130,7 @@ import InlineAddress from "@/components/Address/InlineAddress.vue";
|
||||
import Video from "vue-material-design-icons/Video.vue";
|
||||
import AccountCircle from "vue-material-design-icons/AccountCircle.vue";
|
||||
import AccountMultiple from "vue-material-design-icons/AccountMultiple.vue";
|
||||
import Tag from "@/components/Tag.vue";
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
<template>
|
||||
<article class="bg-white dark:bg-mbz-purple mb-5 mt-4 pb-2 md:p-0">
|
||||
<div class="bg-yellow-2 flex p-2 text-violet-title rounded-t-lg" dir="auto">
|
||||
<article
|
||||
class="bg-white dark:bg-mbz-purple dark:hover:bg-mbz-purple-400 mb-5 mt-4 pb-2 md:p-0 rounded-t-lg"
|
||||
>
|
||||
<div
|
||||
class="bg-mbz-yellow-alt-100 flex p-2 text-violet-title rounded-t-lg"
|
||||
dir="auto"
|
||||
>
|
||||
<figure
|
||||
class="image is-24x24 ltr:pr-1 rtl:pl-1"
|
||||
v-if="participation.actor.avatar"
|
||||
>
|
||||
<img
|
||||
class="is-rounded"
|
||||
class="rounded"
|
||||
:src="participation.actor.avatar.url"
|
||||
alt=""
|
||||
height="24"
|
||||
@@ -157,7 +162,7 @@
|
||||
</span>
|
||||
<o-button
|
||||
v-if="participation.event.participantStats.notApproved > 0"
|
||||
type="is-text"
|
||||
variant="text"
|
||||
@click="
|
||||
gotToWithCheck(participation, {
|
||||
name: RouteName.PARTICIPATIONS,
|
||||
@@ -330,7 +335,7 @@ const defaultOptions: IEventCardOptions = {
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
participation: IParticipant;
|
||||
options: IEventCardOptions;
|
||||
options?: IEventCardOptions;
|
||||
}>(),
|
||||
{
|
||||
options: () => ({
|
||||
|
||||
@@ -7,14 +7,11 @@
|
||||
:message="fieldErrors"
|
||||
:type="{ 'is-danger': fieldErrors }"
|
||||
class="!-mt-2"
|
||||
:labelClass="labelClass"
|
||||
>
|
||||
<template #label>
|
||||
{{ actualLabel }}
|
||||
<span
|
||||
class="is-size-6 has-text-weight-normal"
|
||||
v-if="gettingLocation"
|
||||
>{{ t("Getting location") }}</span
|
||||
>
|
||||
<span v-if="gettingLocation">{{ t("Getting location") }}</span>
|
||||
</template>
|
||||
<p class="control" v-if="canShowLocateMeButton">
|
||||
<o-loading
|
||||
@@ -54,7 +51,7 @@
|
||||
</template>
|
||||
<template #empty>
|
||||
<span v-if="isFetching">{{ t("Searching…") }}</span>
|
||||
<div v-else-if="queryText.length >= 3" class="is-enabled">
|
||||
<div v-else-if="queryText.length >= 3" class="enabled">
|
||||
<span>{{
|
||||
t('No results for "{queryText}"', { queryText })
|
||||
}}</span>
|
||||
@@ -121,12 +118,16 @@ import { useGeocodingAutocomplete } from "@/composition/apollo/config";
|
||||
import { ADDRESS } from "@/graphql/address";
|
||||
import { useReverseGeocode } from "@/composition/apollo/address";
|
||||
import { useLazyQuery } from "@vue/apollo-composable";
|
||||
const MapLeaflet = defineAsyncComponent(() => import("../Map.vue"));
|
||||
const MapLeaflet = defineAsyncComponent(
|
||||
() => import("@/components/LeafletMap.vue")
|
||||
);
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
modelValue: IAddress | null;
|
||||
defaultText?: string | null;
|
||||
label?: string;
|
||||
labelClass?: string;
|
||||
userTimezone?: string;
|
||||
disabled?: boolean;
|
||||
hideMap?: boolean;
|
||||
@@ -134,7 +135,8 @@ const props = withDefaults(
|
||||
placeholder?: string;
|
||||
}>(),
|
||||
{
|
||||
label: "",
|
||||
labelClass: "",
|
||||
defaultText: "",
|
||||
disabled: false,
|
||||
hideMap: false,
|
||||
hideSelected: false,
|
||||
@@ -204,7 +206,7 @@ const checkCurrentPosition = (e: LatLng): boolean => {
|
||||
const { t, locale } = useI18n({ useScope: "global" });
|
||||
|
||||
const actualLabel = computed((): string => {
|
||||
return props.label ?? (t("Find an address") as string);
|
||||
return props.label ?? t("Find an address");
|
||||
});
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
@@ -253,11 +255,14 @@ const asyncData = async (query: string): Promise<void> => {
|
||||
|
||||
const queryText = computed({
|
||||
get() {
|
||||
return selected.value ? addressFullName(selected.value) : "";
|
||||
return (
|
||||
(selected.value ? addressFullName(selected.value) : props.defaultText) ??
|
||||
""
|
||||
);
|
||||
},
|
||||
set(text) {
|
||||
if (text === "" && selected.value?.id) {
|
||||
console.log("doing reset");
|
||||
console.debug("doing reset");
|
||||
resetAddress();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="events-wrapper">
|
||||
<div class="flex flex-col gap-4" v-for="key of keys" :key="key">
|
||||
<h2 class="is-size-5 month-name">
|
||||
<h2 class="month-name">
|
||||
{{ monthName(groupEvents(key)[0]) }}
|
||||
</h2>
|
||||
<event-minimalist-card
|
||||
|
||||
@@ -27,10 +27,6 @@ const videoDetails = computed((): { host: string; uuid: string } | null => {
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
const origin = computed((): string => {
|
||||
return window.location.hostname;
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.peertube {
|
||||
@@ -28,10 +28,6 @@ const videoID = computed((): string | null => {
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
const origin = computed((): string => {
|
||||
return window.location.hostname;
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.youtube {
|
||||
@@ -34,9 +34,9 @@
|
||||
class="flex flex-wrap p-3 bg-white hover:bg-gray-50 dark:bg-violet-3 dark:hover:bg-violet-3/60 border border-gray-300 rounded-lg cursor-pointer peer-checked:ring-primary peer-checked:ring-2 peer-checked:border-transparent"
|
||||
:for="`availableActor-${availableActor?.id}`"
|
||||
>
|
||||
<figure class="" v-if="availableActor?.avatar">
|
||||
<figure class="h-12 w-12" v-if="availableActor?.avatar">
|
||||
<img
|
||||
class="rounded"
|
||||
class="rounded-full h-full w-full object-cover"
|
||||
:src="availableActor.avatar.url"
|
||||
alt=""
|
||||
width="48"
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
>
|
||||
<div class="flex gap-1 p-4">
|
||||
<div class="">
|
||||
<figure class="" v-if="selectedActor.avatar">
|
||||
<figure class="h-12 w-12" v-if="selectedActor.avatar">
|
||||
<img
|
||||
class="rounded"
|
||||
class="rounded-full h-full w-full object-cover"
|
||||
:src="selectedActor.avatar.url"
|
||||
:alt="selectedActor.avatar.alt ?? ''"
|
||||
height="48"
|
||||
@@ -207,7 +207,7 @@ const props = withDefaults(
|
||||
{ inline: true, contacts: () => [] }
|
||||
);
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "update:Contacts"]);
|
||||
const emit = defineEmits(["update:modelValue", "update:contacts"]);
|
||||
|
||||
const selectedActor = computed({
|
||||
get(): IActor | undefined {
|
||||
@@ -252,7 +252,7 @@ const actualContacts = computed({
|
||||
},
|
||||
set(contactsIds: (string | undefined)[]) {
|
||||
emit(
|
||||
"update:Contacts",
|
||||
"update:contacts",
|
||||
actorMembers.value.filter(({ id }) => contactsIds.includes(id))
|
||||
);
|
||||
},
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { IActor, IPerson } from "@/types/actor";
|
||||
import { IPerson } from "@/types/actor";
|
||||
import { EventJoinOptions, ParticipantRole } from "@/types/enums";
|
||||
import { IEvent } from "@/types/event.model";
|
||||
import ParticipationButton from "./ParticipationButton.vue";
|
||||
|
||||
@@ -37,7 +37,7 @@ import { useI18n } from "vue-i18n";
|
||||
import { IEvent } from "@/types/event.model";
|
||||
import ShareModal from "@/components/Share/ShareModal.vue";
|
||||
|
||||
const props = withDefaults(
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
event: IEvent;
|
||||
eventCapacityOK?: boolean;
|
||||
|
||||
@@ -16,8 +16,8 @@ import TagInput from "./TagInput.vue";
|
||||
|
||||
const tags = reactive<ITag[]>([{ title: "Hello", slug: "hello" }]);
|
||||
|
||||
const fetchTags = async (text: string) =>
|
||||
new Promise<ITag[]>((resolve, reject) => {
|
||||
const fetchTags = async () =>
|
||||
new Promise<ITag[]>((resolve) => {
|
||||
resolve([{ title: "Welcome", slug: "welcome" }]);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<template #label>
|
||||
{{ $t("Add some tags") }}
|
||||
<o-tooltip
|
||||
type="dark"
|
||||
variant="dark"
|
||||
:label="
|
||||
$t('You can add tags by hitting the Enter key or by adding a comma')
|
||||
"
|
||||
@@ -77,9 +77,9 @@ const tagsStrings = computed({
|
||||
get(): string[] {
|
||||
return props.modelValue.map((tag: ITag) => tag.title);
|
||||
},
|
||||
set(tagsStrings: string[]) {
|
||||
console.debug("tagsStrings", tagsStrings);
|
||||
const tagEntities = tagsStrings.map((tag: string | ITag) => {
|
||||
set(newTagsStrings: string[]) {
|
||||
console.debug("tagsStrings", newTagsStrings);
|
||||
const tagEntities = newTagsStrings.map((tag: string | ITag) => {
|
||||
if (typeof tag !== "string") {
|
||||
return tag;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user