@frigear-nu/events 0.0.10 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/module.mjs +6 -4
- package/dist/runtime/app/components/EventAdminAddonDialog.d.vue.ts +2 -2
- package/dist/runtime/app/components/EventAdminAddonDialog.vue +3 -4
- package/dist/runtime/app/components/EventAdminAddonDialog.vue.d.ts +2 -2
- package/dist/runtime/app/components/EventAdminAddonGroupDialog.d.vue.ts +2 -2
- package/dist/runtime/app/components/EventAdminAddonGroupDialog.vue +3 -4
- package/dist/runtime/app/components/EventAdminAddonGroupDialog.vue.d.ts +2 -2
- package/dist/runtime/app/components/EventAdminAddonGroups.d.vue.ts +8 -8
- package/dist/runtime/app/components/EventAdminAddonGroups.vue +46 -55
- package/dist/runtime/app/components/EventAdminAddonGroups.vue.d.ts +8 -8
- package/dist/runtime/app/components/EventAdminTicketTypeDialog.d.vue.ts +2 -2
- package/dist/runtime/app/components/EventAdminTicketTypeDialog.vue +3 -4
- package/dist/runtime/app/components/EventAdminTicketTypeDialog.vue.d.ts +2 -2
- package/dist/runtime/app/components/EventCard.vue +7 -12
- package/dist/runtime/app/components/EventFormSlideover.d.vue.ts +13 -0
- package/dist/runtime/app/components/EventFormSlideover.vue +70 -0
- package/dist/runtime/app/components/EventFormSlideover.vue.d.ts +13 -0
- package/dist/runtime/app/components/EventTicketCard.vue +5 -7
- package/dist/runtime/app/components/EventTicketPicker.vue +5 -6
- package/dist/runtime/app/composables/index.d.ts +2 -0
- package/dist/runtime/app/composables/index.js +2 -0
- package/dist/runtime/app/composables/useEventActions.d.ts +26 -0
- package/dist/runtime/app/composables/useEventActions.js +61 -0
- package/dist/runtime/app/composables/useEventLinks.d.ts +12 -0
- package/dist/runtime/app/composables/useEventLinks.js +5 -0
- package/dist/runtime/app/composables/useEvents.d.ts +5 -2
- package/dist/runtime/app/pages/admin-event.vue +33 -21
- package/dist/runtime/app/pages/admin.vue +61 -135
- package/dist/runtime/app/pages/event.d.vue.ts +2 -2
- package/dist/runtime/app/pages/event.vue +113 -152
- package/dist/runtime/app/pages/event.vue.d.ts +2 -2
- package/dist/runtime/app/pages/events.vue +33 -31
- package/dist/runtime/app/pages/tickets.vue +21 -28
- package/dist/runtime/app/tabs/Attendees.d.vue.ts +2 -2
- package/dist/runtime/app/tabs/Attendees.vue +64 -60
- package/dist/runtime/app/tabs/Attendees.vue.d.ts +2 -2
- package/dist/runtime/app/tabs/Details.d.vue.ts +2 -2
- package/dist/runtime/app/tabs/Details.vue +4 -5
- package/dist/runtime/app/tabs/Details.vue.d.ts +2 -2
- package/dist/runtime/app/tabs/Tickets.d.vue.ts +2 -2
- package/dist/runtime/app/tabs/Tickets.vue +92 -99
- package/dist/runtime/app/tabs/Tickets.vue.d.ts +2 -2
- package/dist/runtime/app/utils/admin-event.d.ts +9 -12
- package/dist/runtime/app/utils/admin-event.js +0 -17
- package/dist/runtime/app/widgets/UpcomingEvents.vue +7 -9
- package/dist/runtime/app/widgets/UpcomingEventsStat.vue +5 -6
- package/dist/runtime/i18n/lang/da.json +111 -3
- package/dist/runtime/i18n/lang/en.json +111 -3
- package/dist/runtime/menus.js +2 -4
- package/dist/runtime/server/utils/admin.d.ts +5 -5
- package/dist/runtime/utils/index.d.ts +1 -0
- package/dist/runtime/utils/index.js +1 -0
- package/dist/runtime/utils/links.d.ts +21 -0
- package/dist/runtime/utils/links.js +12 -0
- package/package.json +21 -21
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -25,7 +25,7 @@ const module$1 = defineNuxtModule({
|
|
|
25
25
|
"@frigear-nu/subscriptions": { version: ">=0.0.1", optional: true },
|
|
26
26
|
"@frigear-nu/menu": { version: ">=0.0.1", optional: true },
|
|
27
27
|
"@frigear-nu/widget": { version: ">=0.0.0", optional: true },
|
|
28
|
-
// Provides the
|
|
28
|
+
// Provides the admin route and shell the admin pages live in; the page components come from `@frigear-nu/ui`.
|
|
29
29
|
"@frigear-nu/admin": { version: ">=0.0.0", optional: true }
|
|
30
30
|
},
|
|
31
31
|
async setup(options, nuxt) {
|
|
@@ -53,7 +53,7 @@ const module$1 = defineNuxtModule({
|
|
|
53
53
|
nuxt.options.runtimeConfig.public.events = {
|
|
54
54
|
pages: { events: eventsPath, event: eventPath, tickets: ticketsPath, admin: adminPath, adminEvent: adminEventPath }
|
|
55
55
|
};
|
|
56
|
-
|
|
56
|
+
registerDatabaseTable(nuxt, {
|
|
57
57
|
resolver,
|
|
58
58
|
schema: (dialect) => `./runtime/server/db/schema.${dialect}`
|
|
59
59
|
});
|
|
@@ -101,7 +101,9 @@ const module$1 = defineNuxtModule({
|
|
|
101
101
|
{ name: "useMyTickets", from: resolver.resolve("./runtime/app/composables/useEvents") },
|
|
102
102
|
{ name: "useEventsLocale", from: resolver.resolve("./runtime/app/composables/useEvents") },
|
|
103
103
|
{ name: "useEventsFallbackLocale", from: resolver.resolve("./runtime/app/composables/useEvents") },
|
|
104
|
-
{ name: "useEventsTranslate", from: resolver.resolve("./runtime/app/composables/useEvents") }
|
|
104
|
+
{ name: "useEventsTranslate", from: resolver.resolve("./runtime/app/composables/useEvents") },
|
|
105
|
+
{ name: "useEventLinks", from: resolver.resolve("./runtime/app/composables/useEventLinks") },
|
|
106
|
+
{ name: "useEventActions", from: resolver.resolve("./runtime/app/composables/useEventActions") }
|
|
105
107
|
]);
|
|
106
108
|
addComponentsDir({ path: resolver.resolve("./runtime/app/components") });
|
|
107
109
|
addModulePages(MODULE_NAME, resolver, [
|
|
@@ -124,7 +126,7 @@ const module$1 = defineNuxtModule({
|
|
|
124
126
|
extendWidgets(nuxt, "admin.dashboard.top", { id: "events-upcoming-stat", component: resolver.resolve("./runtime/app/widgets/UpcomingEventsStat.vue"), order: 20 });
|
|
125
127
|
extendWidgets(nuxt, "admin.dashboard.side", { id: "events-upcoming", component: resolver.resolve("./runtime/app/widgets/UpcomingEvents.vue"), order: 10 });
|
|
126
128
|
}
|
|
127
|
-
addOptionalMenuSource(nuxt, { file: resolver.resolve("./runtime/menus"), menu: "
|
|
129
|
+
addOptionalMenuSource(nuxt, { file: resolver.resolve("./runtime/menus"), menu: "account" });
|
|
128
130
|
}
|
|
129
131
|
});
|
|
130
132
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare function open(addonGroup:
|
|
1
|
+
import type { StaffAddon, StaffAddonGroup } from '../utils/admin-event.js';
|
|
2
|
+
declare function open(addonGroup: StaffAddonGroup, currency: string, existing?: StaffAddon): void;
|
|
3
3
|
declare const __VLS_export: import("vue").DefineComponent<{}, {
|
|
4
4
|
open: typeof open;
|
|
5
5
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { fromCents, toCents } from "@frigear-nu/ui/money";
|
|
3
3
|
import { DEFAULT_CURRENCY } from "../../utils";
|
|
4
|
-
import { useAdminAction } from "../utils/admin-event";
|
|
5
4
|
defineOptions({ name: "EventAdminAddonDialog" });
|
|
6
5
|
const emit = defineEmits(["refresh"]);
|
|
7
6
|
const t = useModuleT("events");
|
|
8
7
|
const tr = useEventsTranslate();
|
|
9
|
-
const { busy, run } =
|
|
8
|
+
const { busy, run } = useAction();
|
|
10
9
|
const dialog = ref(false);
|
|
11
10
|
const groupId = ref("");
|
|
12
11
|
const editingAddon = ref(null);
|
|
@@ -40,7 +39,7 @@ const save = () => run(async () => {
|
|
|
40
39
|
}
|
|
41
40
|
dialog.value = false;
|
|
42
41
|
emit("refresh");
|
|
43
|
-
}, t("admin.addonSaved", "Add-on saved."));
|
|
42
|
+
}, { success: t("admin.addonSaved", "Add-on saved.") });
|
|
44
43
|
</script>
|
|
45
44
|
|
|
46
45
|
<template>
|
|
@@ -95,7 +94,7 @@ const save = () => run(async () => {
|
|
|
95
94
|
<template #footer>
|
|
96
95
|
<div class="flex w-full justify-end gap-2">
|
|
97
96
|
<UButton
|
|
98
|
-
variant="
|
|
97
|
+
variant="outline"
|
|
99
98
|
color="neutral"
|
|
100
99
|
:label="t('admin.cancel', 'Cancel')"
|
|
101
100
|
@click="dialog = false"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare function open(addonGroup:
|
|
1
|
+
import type { StaffAddon, StaffAddonGroup } from '../utils/admin-event.js';
|
|
2
|
+
declare function open(addonGroup: StaffAddonGroup, currency: string, existing?: StaffAddon): void;
|
|
3
3
|
declare const __VLS_export: import("vue").DefineComponent<{}, {
|
|
4
4
|
open: typeof open;
|
|
5
5
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare function open(ticketType:
|
|
1
|
+
import type { StaffAddonGroup, StaffTicketType } from '../utils/admin-event.js';
|
|
2
|
+
declare function open(ticketType: StaffTicketType, existing?: StaffAddonGroup): void;
|
|
3
3
|
declare const __VLS_export: import("vue").DefineComponent<{}, {
|
|
4
4
|
open: typeof open;
|
|
5
5
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { useAdminAction } from "../utils/admin-event";
|
|
3
2
|
defineOptions({ name: "EventAdminAddonGroupDialog" });
|
|
4
3
|
const emit = defineEmits(["refresh"]);
|
|
5
4
|
const t = useModuleT("events");
|
|
6
5
|
const tr = useEventsTranslate();
|
|
7
|
-
const { busy, run } =
|
|
6
|
+
const { busy, run } = useAction();
|
|
8
7
|
const dialog = ref(false);
|
|
9
8
|
const ticketTypeId = ref("");
|
|
10
9
|
const editingGroup = ref(null);
|
|
@@ -25,7 +24,7 @@ const save = () => run(async () => {
|
|
|
25
24
|
}
|
|
26
25
|
dialog.value = false;
|
|
27
26
|
emit("refresh");
|
|
28
|
-
}, t("admin.groupSaved", "Add-on group saved."));
|
|
27
|
+
}, { success: t("admin.groupSaved", "Add-on group saved.") });
|
|
29
28
|
</script>
|
|
30
29
|
|
|
31
30
|
<template>
|
|
@@ -61,7 +60,7 @@ const save = () => run(async () => {
|
|
|
61
60
|
<template #footer>
|
|
62
61
|
<div class="flex w-full justify-end gap-2">
|
|
63
62
|
<UButton
|
|
64
|
-
variant="
|
|
63
|
+
variant="outline"
|
|
65
64
|
color="neutral"
|
|
66
65
|
:label="t('admin.cancel', 'Cancel')"
|
|
67
66
|
@click="dialog = false"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare function open(ticketType:
|
|
1
|
+
import type { StaffAddonGroup, StaffTicketType } from '../utils/admin-event.js';
|
|
2
|
+
declare function open(ticketType: StaffTicketType, existing?: StaffAddonGroup): void;
|
|
3
3
|
declare const __VLS_export: import("vue").DefineComponent<{}, {
|
|
4
4
|
open: typeof open;
|
|
5
5
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { StaffAddon, StaffAddonGroup, StaffTicketType } from '../utils/admin-event.js';
|
|
2
2
|
type __VLS_Props = {
|
|
3
|
-
ticketType:
|
|
3
|
+
ticketType: StaffTicketType;
|
|
4
4
|
};
|
|
5
5
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
6
|
refresh: () => any;
|
|
7
7
|
addGroup: () => any;
|
|
8
|
-
editGroup: (group:
|
|
9
|
-
addAddon: (group:
|
|
10
|
-
editAddon: (group:
|
|
8
|
+
editGroup: (group: StaffAddonGroup) => any;
|
|
9
|
+
addAddon: (group: StaffAddonGroup) => any;
|
|
10
|
+
editAddon: (group: StaffAddonGroup, addon: StaffAddon) => any;
|
|
11
11
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
12
|
onRefresh?: (() => any) | undefined;
|
|
13
13
|
onAddGroup?: (() => any) | undefined;
|
|
14
|
-
onEditGroup?: ((group:
|
|
15
|
-
onAddAddon?: ((group:
|
|
16
|
-
onEditAddon?: ((group:
|
|
14
|
+
onEditGroup?: ((group: StaffAddonGroup) => any) | undefined;
|
|
15
|
+
onAddAddon?: ((group: StaffAddonGroup) => any) | undefined;
|
|
16
|
+
onEditAddon?: ((group: StaffAddonGroup, addon: StaffAddon) => any) | undefined;
|
|
17
17
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
18
18
|
declare const _default: typeof __VLS_export;
|
|
19
19
|
export default _default;
|
|
@@ -1,30 +1,55 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { formatMoney as formatPrice } from "@frigear-nu/ui/money";
|
|
3
|
-
import { useAdminAction } from "../utils/admin-event";
|
|
4
2
|
defineOptions({ name: "EventAdminAddonGroups" });
|
|
5
3
|
defineProps({
|
|
6
4
|
ticketType: { type: Object, required: true }
|
|
7
5
|
});
|
|
8
6
|
const emit = defineEmits(["refresh", "addGroup", "editGroup", "addAddon", "editAddon"]);
|
|
9
7
|
const t = useModuleT("events");
|
|
10
|
-
const
|
|
8
|
+
const format = useFormat();
|
|
11
9
|
const tr = useEventsTranslate();
|
|
12
10
|
const confirmAction = useConfirmDialog();
|
|
13
|
-
const { run } =
|
|
11
|
+
const { run } = useAction();
|
|
14
12
|
const removeGroup = async (addonGroup) => {
|
|
15
|
-
|
|
13
|
+
const title = tr(addonGroup.title);
|
|
14
|
+
if (!await confirmAction({
|
|
15
|
+
title: t("admin.confirmRemoveGroup", "Delete {name}?", { name: title }),
|
|
16
|
+
description: t("admin.confirmRemoveGroupDescription", "Its choices are deleted too. Tickets already bought keep the choices they made."),
|
|
17
|
+
confirmText: t("admin.removeGroup", "Delete add-on group"),
|
|
18
|
+
destructive: true
|
|
19
|
+
})) return;
|
|
16
20
|
return run(async () => {
|
|
17
21
|
await $fetch(`/api/events/admin/addon-groups/${addonGroup.id}`, { method: "DELETE" });
|
|
18
22
|
emit("refresh");
|
|
19
|
-
});
|
|
23
|
+
}, { success: t("admin.groupDeleted", "Deleted {name}", { name: title }) });
|
|
20
24
|
};
|
|
21
25
|
const removeAddon = async (existing) => {
|
|
22
|
-
|
|
26
|
+
const label = tr(existing.label);
|
|
27
|
+
if (!await confirmAction({
|
|
28
|
+
title: t("admin.confirmRemoveAddon", "Delete {name}?", { name: label }),
|
|
29
|
+
description: t("admin.confirmRemoveAddonDescription", "Tickets already bought keep the choice they made."),
|
|
30
|
+
confirmText: t("admin.removeAddon", "Delete choice"),
|
|
31
|
+
destructive: true
|
|
32
|
+
})) return;
|
|
23
33
|
return run(async () => {
|
|
24
34
|
await $fetch(`/api/events/admin/addons/${existing.id}`, { method: "DELETE" });
|
|
25
35
|
emit("refresh");
|
|
26
|
-
});
|
|
36
|
+
}, { success: t("admin.addonDeleted", "Deleted {name}", { name: label }) });
|
|
27
37
|
};
|
|
38
|
+
const groupMenu = (addonGroup) => [
|
|
39
|
+
[
|
|
40
|
+
{ label: t("admin.addAddon", "Add choice"), icon: "i-lucide-plus", onSelect: () => emit("addAddon", addonGroup) },
|
|
41
|
+
{ label: t("admin.editGroup", "Edit add-on group"), icon: "i-lucide-pencil", onSelect: () => emit("editGroup", addonGroup) }
|
|
42
|
+
],
|
|
43
|
+
[{ label: t("admin.removeGroup", "Delete add-on group"), icon: "i-lucide-trash-2", color: "error", onSelect: () => {
|
|
44
|
+
void removeGroup(addonGroup);
|
|
45
|
+
} }]
|
|
46
|
+
];
|
|
47
|
+
const addonMenu = (addonGroup, item) => [
|
|
48
|
+
[{ label: t("admin.editAddon", "Edit choice"), icon: "i-lucide-pencil", onSelect: () => emit("editAddon", addonGroup, item) }],
|
|
49
|
+
[{ label: t("admin.removeAddon", "Delete choice"), icon: "i-lucide-trash-2", color: "error", onSelect: () => {
|
|
50
|
+
void removeAddon(item);
|
|
51
|
+
} }]
|
|
52
|
+
];
|
|
28
53
|
</script>
|
|
29
54
|
|
|
30
55
|
<template>
|
|
@@ -32,42 +57,21 @@ const removeAddon = async (existing) => {
|
|
|
32
57
|
<div
|
|
33
58
|
v-for="addonGroup in ticketType.addonGroups"
|
|
34
59
|
:key="addonGroup.id"
|
|
35
|
-
class="border-default overflow-hidden rounded-lg border
|
|
60
|
+
class="border-default bg-default overflow-hidden rounded-lg border"
|
|
36
61
|
>
|
|
37
62
|
<div class="border-default flex items-center justify-between gap-2 border-b px-3 py-2">
|
|
38
63
|
<div class="min-w-0 text-sm">
|
|
39
|
-
<span class="font-medium">{{ tr(addonGroup.title) }}</span>
|
|
64
|
+
<span class="text-highlighted font-medium">{{ tr(addonGroup.title) }}</span>
|
|
40
65
|
<span class="text-muted ms-2 text-xs">
|
|
41
66
|
{{ addonGroup.required ? t("admin.groupRequired", "required") : t("admin.groupOptional", "optional") }}
|
|
42
67
|
· {{ addonGroup.multiple ? t("admin.groupMultiple", "several choices") : t("admin.groupSingle", "one choice") }}
|
|
43
68
|
</span>
|
|
44
69
|
</div>
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
size="xs"
|
|
51
|
-
:aria-label="t('admin.addAddon', 'Add choice')"
|
|
52
|
-
@click="emit('addAddon', addonGroup)"
|
|
53
|
-
/>
|
|
54
|
-
<UButton
|
|
55
|
-
icon="i-lucide-pencil"
|
|
56
|
-
color="neutral"
|
|
57
|
-
variant="ghost"
|
|
58
|
-
size="xs"
|
|
59
|
-
:aria-label="t('admin.edit', 'Edit')"
|
|
60
|
-
@click="emit('editGroup', addonGroup)"
|
|
61
|
-
/>
|
|
62
|
-
<UButton
|
|
63
|
-
icon="i-lucide-trash"
|
|
64
|
-
color="error"
|
|
65
|
-
variant="ghost"
|
|
66
|
-
size="xs"
|
|
67
|
-
:aria-label="t('admin.remove', 'Delete')"
|
|
68
|
-
@click="removeGroup(addonGroup)"
|
|
69
|
-
/>
|
|
70
|
-
</div>
|
|
70
|
+
<RowMenu
|
|
71
|
+
:items="groupMenu(addonGroup)"
|
|
72
|
+
:subject="tr(addonGroup.title)"
|
|
73
|
+
size="xs"
|
|
74
|
+
/>
|
|
71
75
|
</div>
|
|
72
76
|
<ul
|
|
73
77
|
v-if="addonGroup.addons.length"
|
|
@@ -80,26 +84,13 @@ const removeAddon = async (existing) => {
|
|
|
80
84
|
>
|
|
81
85
|
<div>
|
|
82
86
|
{{ tr(item.label) }}
|
|
83
|
-
<span class="text-muted">· {{ item.price === 0 ? t("admin.included", "Included") : `+ ${
|
|
84
|
-
</div>
|
|
85
|
-
<div class="flex shrink-0 gap-1">
|
|
86
|
-
<UButton
|
|
87
|
-
icon="i-lucide-pencil"
|
|
88
|
-
color="neutral"
|
|
89
|
-
variant="ghost"
|
|
90
|
-
size="xs"
|
|
91
|
-
:aria-label="t('admin.edit', 'Edit')"
|
|
92
|
-
@click="emit('editAddon', addonGroup, item)"
|
|
93
|
-
/>
|
|
94
|
-
<UButton
|
|
95
|
-
icon="i-lucide-trash"
|
|
96
|
-
color="error"
|
|
97
|
-
variant="ghost"
|
|
98
|
-
size="xs"
|
|
99
|
-
:aria-label="t('admin.remove', 'Delete')"
|
|
100
|
-
@click="removeAddon(item)"
|
|
101
|
-
/>
|
|
87
|
+
<span class="text-muted">· {{ item.price === 0 ? t("admin.included", "Included") : `+ ${format.money(item.price, ticketType.currency)}` }}<template v-if="item.capacity !== null"> · {{ t("admin.capacity", "Capacity").toLowerCase() }} {{ item.capacity }}</template></span>
|
|
102
88
|
</div>
|
|
89
|
+
<RowMenu
|
|
90
|
+
:items="addonMenu(addonGroup, item)"
|
|
91
|
+
:subject="tr(item.label)"
|
|
92
|
+
size="xs"
|
|
93
|
+
/>
|
|
103
94
|
</li>
|
|
104
95
|
</ul>
|
|
105
96
|
<p
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { StaffAddon, StaffAddonGroup, StaffTicketType } from '../utils/admin-event.js';
|
|
2
2
|
type __VLS_Props = {
|
|
3
|
-
ticketType:
|
|
3
|
+
ticketType: StaffTicketType;
|
|
4
4
|
};
|
|
5
5
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
6
|
refresh: () => any;
|
|
7
7
|
addGroup: () => any;
|
|
8
|
-
editGroup: (group:
|
|
9
|
-
addAddon: (group:
|
|
10
|
-
editAddon: (group:
|
|
8
|
+
editGroup: (group: StaffAddonGroup) => any;
|
|
9
|
+
addAddon: (group: StaffAddonGroup) => any;
|
|
10
|
+
editAddon: (group: StaffAddonGroup, addon: StaffAddon) => any;
|
|
11
11
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
12
12
|
onRefresh?: (() => any) | undefined;
|
|
13
13
|
onAddGroup?: (() => any) | undefined;
|
|
14
|
-
onEditGroup?: ((group:
|
|
15
|
-
onAddAddon?: ((group:
|
|
16
|
-
onEditAddon?: ((group:
|
|
14
|
+
onEditGroup?: ((group: StaffAddonGroup) => any) | undefined;
|
|
15
|
+
onAddAddon?: ((group: StaffAddonGroup) => any) | undefined;
|
|
16
|
+
onEditAddon?: ((group: StaffAddonGroup, addon: StaffAddon) => any) | undefined;
|
|
17
17
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
18
18
|
declare const _default: typeof __VLS_export;
|
|
19
19
|
export default _default;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { StaffTicketType } from '../utils/admin-event.js';
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
eventId: string;
|
|
4
4
|
/** Membership rules are only offered when @frigear-nu/subscriptions is installed. */
|
|
@@ -8,7 +8,7 @@ type __VLS_Props = {
|
|
|
8
8
|
value: string;
|
|
9
9
|
}>;
|
|
10
10
|
};
|
|
11
|
-
declare function open(ticketType?:
|
|
11
|
+
declare function open(ticketType?: StaffTicketType): void;
|
|
12
12
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
13
13
|
open: typeof open;
|
|
14
14
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { toCents, fromCents } from "@frigear-nu/ui/money";
|
|
3
3
|
import { DEFAULT_CURRENCY, ticketMdcData } from "../../utils";
|
|
4
|
-
import { useAdminAction } from "../utils/admin-event";
|
|
5
4
|
defineOptions({ name: "EventAdminTicketTypeDialog" });
|
|
6
5
|
const props = defineProps({
|
|
7
6
|
eventId: { type: String, required: true },
|
|
@@ -12,7 +11,7 @@ const emit = defineEmits(["refresh"]);
|
|
|
12
11
|
const t = useModuleT("events");
|
|
13
12
|
const locale = useEventsLocale();
|
|
14
13
|
const tr = useEventsTranslate();
|
|
15
|
-
const { busy, run } =
|
|
14
|
+
const { busy, run } = useAction();
|
|
16
15
|
const modes = computed(() => [
|
|
17
16
|
{ label: t("admin.ruleNone", "Nobody"), value: "none" },
|
|
18
17
|
{ label: t("admin.ruleAny", "Any membership"), value: "any" },
|
|
@@ -53,7 +52,7 @@ const save = () => run(async () => {
|
|
|
53
52
|
}
|
|
54
53
|
dialog.value = false;
|
|
55
54
|
emit("refresh");
|
|
56
|
-
}, t("admin.typeSaved", "Ticket type saved."));
|
|
55
|
+
}, { success: t("admin.typeSaved", "Ticket type saved.") });
|
|
57
56
|
</script>
|
|
58
57
|
|
|
59
58
|
<template>
|
|
@@ -157,7 +156,7 @@ const save = () => run(async () => {
|
|
|
157
156
|
<template #footer>
|
|
158
157
|
<div class="flex w-full justify-end gap-2">
|
|
159
158
|
<UButton
|
|
160
|
-
variant="
|
|
159
|
+
variant="outline"
|
|
161
160
|
color="neutral"
|
|
162
161
|
:label="t('admin.cancel', 'Cancel')"
|
|
163
162
|
@click="dialog = false"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { StaffTicketType } from '../utils/admin-event.js';
|
|
2
2
|
type __VLS_Props = {
|
|
3
3
|
eventId: string;
|
|
4
4
|
/** Membership rules are only offered when @frigear-nu/subscriptions is installed. */
|
|
@@ -8,7 +8,7 @@ type __VLS_Props = {
|
|
|
8
8
|
value: string;
|
|
9
9
|
}>;
|
|
10
10
|
};
|
|
11
|
-
declare function open(ticketType?:
|
|
11
|
+
declare function open(ticketType?: StaffTicketType): void;
|
|
12
12
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
13
13
|
open: typeof open;
|
|
14
14
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
@@ -4,14 +4,14 @@ defineProps({
|
|
|
4
4
|
to: { type: String, required: true }
|
|
5
5
|
});
|
|
6
6
|
const t = useModuleT("events");
|
|
7
|
-
const
|
|
7
|
+
const format = useFormat();
|
|
8
8
|
const tr = useEventsTranslate();
|
|
9
9
|
</script>
|
|
10
10
|
|
|
11
11
|
<template>
|
|
12
12
|
<NuxtLink
|
|
13
13
|
:to="to"
|
|
14
|
-
class="group flex flex-col overflow-hidden rounded-
|
|
14
|
+
class="group bg-default ring-default flex flex-col overflow-hidden rounded-lg ring transition hover:shadow-lg"
|
|
15
15
|
>
|
|
16
16
|
<img
|
|
17
17
|
v-if="event.image"
|
|
@@ -33,26 +33,21 @@ const tr = useEventsTranslate();
|
|
|
33
33
|
>
|
|
34
34
|
{{ t("members", "Members") }}
|
|
35
35
|
</UBadge>
|
|
36
|
-
<h3 class="text-
|
|
36
|
+
<h3 class="text-highlighted font-semibold">
|
|
37
37
|
{{ tr(event.name) }}
|
|
38
38
|
</h3>
|
|
39
|
-
<p class="text-
|
|
40
|
-
<
|
|
41
|
-
:datetime="event.startsAt"
|
|
42
|
-
:locale="locale"
|
|
43
|
-
date-style="full"
|
|
44
|
-
time-style="short"
|
|
45
|
-
/><template v-if="event.location">
|
|
39
|
+
<p class="text-muted text-sm">
|
|
40
|
+
{{ format.dateTime(event.startsAt, { dateStyle: "full" }) }}<template v-if="event.location">
|
|
46
41
|
· {{ tr(event.location) }}
|
|
47
42
|
</template>
|
|
48
43
|
</p>
|
|
49
44
|
<p
|
|
50
45
|
v-if="event.description"
|
|
51
|
-
class="line-clamp-3 text-sm
|
|
46
|
+
class="text-muted line-clamp-3 text-sm"
|
|
52
47
|
>
|
|
53
48
|
{{ tr(event.description) }}
|
|
54
49
|
</p>
|
|
55
|
-
<span class="mt-auto inline-flex items-center gap-1 pt-2 text-sm font-medium
|
|
50
|
+
<span class="text-primary mt-auto inline-flex items-center gap-1 pt-2 text-sm font-medium">
|
|
56
51
|
{{ t("viewEvent", "View event") }}
|
|
57
52
|
<UIcon
|
|
58
53
|
name="i-lucide-arrow-right"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
2
|
+
close: (created: false | {
|
|
3
|
+
id: string;
|
|
4
|
+
slug: string;
|
|
5
|
+
}) => any;
|
|
6
|
+
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
7
|
+
onClose?: ((created: false | {
|
|
8
|
+
id: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
}) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
defineOptions({ name: "EventFormSlideover" });
|
|
3
|
+
const emit = defineEmits(["close"]);
|
|
4
|
+
const t = useModuleT("events");
|
|
5
|
+
const tr = useEventsTranslate();
|
|
6
|
+
const { busy, run } = useAction();
|
|
7
|
+
const draft = reactive({ name: void 0, slug: "", startsAt: "", location: void 0 });
|
|
8
|
+
const slugify = (value) => value.toLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
9
|
+
const draftName = computed(() => tr(draft.name));
|
|
10
|
+
watch(draftName, (name, previous) => {
|
|
11
|
+
if (draft.slug === slugify(previous)) draft.slug = slugify(name);
|
|
12
|
+
});
|
|
13
|
+
async function save() {
|
|
14
|
+
const created = await run(
|
|
15
|
+
() => $fetch("/api/events/admin/events", {
|
|
16
|
+
method: "POST",
|
|
17
|
+
body: { name: draft.name, slug: draft.slug, startsAt: draft.startsAt, location: draft.location || null, status: "draft" }
|
|
18
|
+
}),
|
|
19
|
+
{ success: t("admin.created", "Event created") }
|
|
20
|
+
);
|
|
21
|
+
if (created) emit("close", created);
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<FormSlideover
|
|
27
|
+
form-id="event-form"
|
|
28
|
+
:title="t('admin.create', 'New event')"
|
|
29
|
+
:description="t('admin.createDescription', 'It is saved as a draft until you publish it.')"
|
|
30
|
+
:submit-label="t('admin.createAction', 'Create draft')"
|
|
31
|
+
:loading="busy"
|
|
32
|
+
:disabled="!draftName"
|
|
33
|
+
@close="emit('close', false)"
|
|
34
|
+
>
|
|
35
|
+
<form
|
|
36
|
+
id="event-form"
|
|
37
|
+
class="flex flex-col gap-4"
|
|
38
|
+
@submit.prevent="save"
|
|
39
|
+
>
|
|
40
|
+
<UFormField :label="t('admin.name', 'Name')">
|
|
41
|
+
<TranslatedInput
|
|
42
|
+
v-model="draft.name"
|
|
43
|
+
required
|
|
44
|
+
/>
|
|
45
|
+
</UFormField>
|
|
46
|
+
<UFormField
|
|
47
|
+
:label="t('admin.slug', 'URL name')"
|
|
48
|
+
:description="t('admin.slugHelp', 'Lowercase letters, numbers and dashes.')"
|
|
49
|
+
>
|
|
50
|
+
<UInput
|
|
51
|
+
v-model="draft.slug"
|
|
52
|
+
class="w-full"
|
|
53
|
+
required
|
|
54
|
+
pattern="[a-z0-9]+(-[a-z0-9]+)*"
|
|
55
|
+
/>
|
|
56
|
+
</UFormField>
|
|
57
|
+
<UFormField :label="t('admin.starts', 'Starts')">
|
|
58
|
+
<UInput
|
|
59
|
+
v-model="draft.startsAt"
|
|
60
|
+
type="datetime-local"
|
|
61
|
+
class="w-full"
|
|
62
|
+
required
|
|
63
|
+
/>
|
|
64
|
+
</UFormField>
|
|
65
|
+
<UFormField :label="t('admin.location', 'Location')">
|
|
66
|
+
<TranslatedInput v-model="draft.location" />
|
|
67
|
+
</UFormField>
|
|
68
|
+
</form>
|
|
69
|
+
</FormSlideover>
|
|
70
|
+
</template>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
2
|
+
close: (created: false | {
|
|
3
|
+
id: string;
|
|
4
|
+
slug: string;
|
|
5
|
+
}) => any;
|
|
6
|
+
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
7
|
+
onClose?: ((created: false | {
|
|
8
|
+
id: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
}) => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { renderSVG } from "uqr";
|
|
3
|
-
import { formatMoney as formatPrice } from "@frigear-nu/ui/money";
|
|
4
3
|
const props = defineProps({
|
|
5
4
|
ticket: { type: Object, required: true },
|
|
6
5
|
to: { type: String, required: false }
|
|
7
6
|
});
|
|
8
7
|
const emit = defineEmits(["pay"]);
|
|
9
8
|
const t = useModuleT("events");
|
|
10
|
-
const
|
|
9
|
+
const format = useFormat();
|
|
11
10
|
const tr = useEventsTranslate();
|
|
12
|
-
const colors = { paid: "success", pending: "warning", cancelled: "neutral", expired: "neutral", refunded: "error" };
|
|
13
11
|
const qr = computed(() => props.ticket.code ? `data:image/svg+xml;utf8,${encodeURIComponent(renderSVG(props.ticket.code, { border: 1 }))}` : null);
|
|
14
12
|
const showQr = ref(false);
|
|
15
13
|
</script>
|
|
@@ -18,7 +16,7 @@ const showQr = ref(false);
|
|
|
18
16
|
<UCard :ui="{ body: 'flex flex-col gap-3' }">
|
|
19
17
|
<div class="flex items-start gap-2">
|
|
20
18
|
<div>
|
|
21
|
-
<h3 class="font-semibold">
|
|
19
|
+
<h3 class="text-highlighted font-semibold">
|
|
22
20
|
{{ tr(ticket.eventName) }}
|
|
23
21
|
</h3>
|
|
24
22
|
<p class="text-sm text-muted">
|
|
@@ -32,14 +30,14 @@ const showQr = ref(false);
|
|
|
32
30
|
</div>
|
|
33
31
|
<UBadge
|
|
34
32
|
class="ml-auto capitalize"
|
|
35
|
-
:color="
|
|
33
|
+
:color="statusColor(ticket.status, { refunded: 'error' })"
|
|
36
34
|
variant="subtle"
|
|
37
35
|
>
|
|
38
36
|
{{ t(`tickets.status.${ticket.status}`, ticket.status) }}
|
|
39
37
|
</UBadge>
|
|
40
38
|
</div>
|
|
41
39
|
<p class="text-sm">
|
|
42
|
-
{{ ticket.amount === 0 ? t("detail.tickets.free", "Free") :
|
|
40
|
+
{{ ticket.amount === 0 ? t("detail.tickets.free", "Free") : format.money(ticket.amount, ticket.currency) }}
|
|
43
41
|
<UBadge
|
|
44
42
|
v-if="ticket.checkedInAt"
|
|
45
43
|
color="info"
|
|
@@ -76,7 +74,7 @@ const showQr = ref(false);
|
|
|
76
74
|
<img
|
|
77
75
|
v-if="showQr && qr"
|
|
78
76
|
:src="qr"
|
|
79
|
-
alt="Ticket QR code"
|
|
77
|
+
:alt="t('tickets.qrAlt', 'Ticket QR code')"
|
|
80
78
|
class="mx-auto w-56 rounded-md bg-white p-2"
|
|
81
79
|
>
|
|
82
80
|
</UCard>
|