@frigear-nu/events 0.1.1 → 0.1.3
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.d.mts +105 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +40 -31
- package/dist/runtime/app/components/EventAddonGroupSlideover.d.vue.ts +18 -0
- package/dist/runtime/app/components/EventAddonGroupSlideover.vue +66 -0
- package/dist/runtime/app/components/EventAddonGroupSlideover.vue.d.ts +18 -0
- package/dist/runtime/app/components/EventAddonSlideover.d.vue.ts +20 -0
- package/dist/runtime/app/components/EventAddonSlideover.vue +103 -0
- package/dist/runtime/app/components/EventAddonSlideover.vue.d.ts +20 -0
- package/dist/runtime/app/components/EventAdminAddonGroups.d.vue.ts +1 -9
- package/dist/runtime/app/components/EventAdminAddonGroups.vue +6 -48
- package/dist/runtime/app/components/EventAdminAddonGroups.vue.d.ts +1 -9
- package/dist/runtime/app/components/EventFormSlideover.vue +45 -23
- package/dist/runtime/app/components/EventTicketCard.vue +59 -62
- package/dist/runtime/app/components/EventTicketTypeSlideover.d.vue.ts +20 -0
- package/dist/runtime/app/components/EventTicketTypeSlideover.vue +176 -0
- package/dist/runtime/app/components/EventTicketTypeSlideover.vue.d.ts +20 -0
- package/dist/runtime/app/composables/index.d.ts +2 -0
- package/dist/runtime/app/composables/index.js +1 -0
- package/dist/runtime/app/composables/useEventActions.d.ts +3 -3
- package/dist/runtime/app/composables/useEventActions.js +9 -4
- package/dist/runtime/app/composables/useEventCatalogActions.d.ts +33 -0
- package/dist/runtime/app/composables/useEventCatalogActions.js +107 -0
- package/dist/runtime/app/composables/useEvents.d.ts +7 -6
- package/dist/runtime/app/composables/useEvents.js +17 -10
- package/dist/runtime/app/pages/admin-event.vue +71 -136
- package/dist/runtime/app/pages/admin.vue +91 -29
- package/dist/runtime/app/pages/event.vue +8 -4
- package/dist/runtime/app/pages/tickets.vue +24 -2
- package/dist/runtime/app/tabs/Attendees.vue +78 -39
- package/dist/runtime/app/tabs/Details.d.vue.ts +1 -1
- package/dist/runtime/app/tabs/Details.vue +112 -30
- package/dist/runtime/app/tabs/Details.vue.d.ts +1 -1
- package/dist/runtime/app/tabs/Tickets.vue +105 -132
- package/dist/runtime/app/utils/admin-event.d.ts +53 -38
- package/dist/runtime/app/utils/admin-event.js +14 -0
- package/dist/runtime/app/widgets/UpcomingEvents.vue +2 -1
- package/dist/runtime/app/widgets/UpcomingEventsStat.vue +2 -1
- package/dist/runtime/i18n/lang/da.json +24 -3
- package/dist/runtime/i18n/lang/en.json +24 -3
- package/dist/runtime/server/bootstrap/my-tickets.d.ts +7 -0
- package/dist/runtime/server/{routes/public/tickets-me.get.js → bootstrap/my-tickets.js} +2 -2
- package/dist/runtime/server/routes/admin/addon-group.delete.js +6 -3
- package/dist/runtime/server/routes/admin/addon-group.patch.js +6 -4
- package/dist/runtime/server/routes/admin/addon-groups.post.js +8 -6
- package/dist/runtime/server/routes/admin/addon.delete.js +6 -3
- package/dist/runtime/server/routes/admin/addon.patch.js +8 -5
- package/dist/runtime/server/routes/admin/addons.post.js +8 -6
- package/dist/runtime/server/routes/admin/attendees.get.js +38 -8
- package/dist/runtime/server/routes/{public → admin}/check-in.post.js +4 -3
- package/dist/runtime/server/routes/admin/event-clone.post.js +37 -19
- package/dist/runtime/server/routes/admin/event.delete.js +7 -4
- package/dist/runtime/server/routes/admin/event.get.js +4 -2
- package/dist/runtime/server/routes/admin/event.patch.js +4 -2
- package/dist/runtime/server/routes/admin/events.get.js +36 -3
- package/dist/runtime/server/routes/admin/events.post.js +3 -4
- package/dist/runtime/server/routes/admin/membership-options.get.js +3 -2
- package/dist/runtime/server/routes/admin/ticket-cancel.post.js +7 -8
- package/dist/runtime/server/routes/admin/ticket-refund.post.js +7 -5
- package/dist/runtime/server/routes/admin/ticket-type.delete.js +7 -4
- package/dist/runtime/server/routes/admin/ticket-type.patch.js +4 -2
- package/dist/runtime/server/routes/admin/ticket-types.post.js +10 -7
- package/dist/runtime/server/routes/admin/upcoming.get.js +7 -3
- package/dist/runtime/server/routes/me/ticket-pay.post.js +13 -0
- package/dist/runtime/server/routes/me/ticket.get.js +6 -0
- package/dist/runtime/server/routes/me/tickets.get.js +2 -0
- package/dist/runtime/server/routes/public/event.get.js +5 -2
- package/dist/runtime/server/routes/public/purchase.post.js +3 -1
- package/dist/runtime/server/utils/admin-dto.d.ts +30 -0
- package/dist/runtime/server/utils/admin-dto.js +101 -0
- package/dist/runtime/server/utils/admin-schemas.js +2 -1
- package/dist/runtime/server/utils/admin.d.ts +3 -1
- package/dist/runtime/server/utils/admin.js +20 -6
- package/dist/runtime/server/utils/auth.d.ts +5 -4
- package/dist/runtime/server/utils/auth.js +6 -7
- package/dist/runtime/server/utils/tickets.js +6 -11
- package/dist/runtime/utils/api.d.ts +48 -0
- package/dist/runtime/utils/api.js +51 -0
- package/dist/runtime/utils/index.d.ts +2 -1
- package/dist/runtime/utils/index.js +1 -0
- package/dist/types.d.mts +1 -1
- package/package.json +21 -16
- package/dist/runtime/app/components/EventAdminAddonDialog.d.vue.ts +0 -11
- package/dist/runtime/app/components/EventAdminAddonDialog.vue +0 -112
- package/dist/runtime/app/components/EventAdminAddonDialog.vue.d.ts +0 -11
- package/dist/runtime/app/components/EventAdminAddonGroupDialog.d.vue.ts +0 -11
- package/dist/runtime/app/components/EventAdminAddonGroupDialog.vue +0 -78
- package/dist/runtime/app/components/EventAdminAddonGroupDialog.vue.d.ts +0 -11
- package/dist/runtime/app/components/EventAdminTicketTypeDialog.d.vue.ts +0 -20
- package/dist/runtime/app/components/EventAdminTicketTypeDialog.vue +0 -174
- package/dist/runtime/app/components/EventAdminTicketTypeDialog.vue.d.ts +0 -20
- package/dist/runtime/server/routes/public/ticket-pay.post.js +0 -10
- package/dist/runtime/server/routes/public/ticket.get.js +0 -4
- /package/dist/runtime/server/routes/{public → admin}/check-in.post.d.ts +0 -0
- /package/dist/runtime/server/routes/{public → me}/ticket-pay.post.d.ts +0 -0
- /package/dist/runtime/server/routes/{public → me}/ticket.get.d.ts +0 -0
- /package/dist/runtime/server/routes/{public/tickets-me.get.d.ts → me/tickets.get.d.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frigear-nu/events",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Events with ticket types, addons, capacity, membership requirements, Stripe payments and QR check-in for the frigear ecosystem, built on @frigear-nu/payments.",
|
|
5
5
|
"homepage": "https://docs.frigear.dev/modules/events",
|
|
6
6
|
"repository": {
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
"types": "./dist/runtime/utils/index.d.ts",
|
|
22
22
|
"import": "./dist/runtime/utils/index.js",
|
|
23
23
|
"default": "./dist/runtime/utils/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./api": {
|
|
26
|
+
"types": "./dist/runtime/utils/api.d.ts",
|
|
27
|
+
"import": "./dist/runtime/utils/api.js",
|
|
28
|
+
"default": "./dist/runtime/utils/api.js"
|
|
24
29
|
}
|
|
25
30
|
},
|
|
26
31
|
"files": [
|
|
@@ -30,15 +35,15 @@
|
|
|
30
35
|
"playground"
|
|
31
36
|
],
|
|
32
37
|
"dependencies": {
|
|
33
|
-
"@frigear-nu/admin": "0.1.
|
|
34
|
-
"@frigear-nu/module-kit": "1.1.
|
|
35
|
-
"@frigear-nu/payments": "0.1.
|
|
36
|
-
"@frigear-nu/stripe": "0.1.
|
|
37
|
-
"@frigear-nu/subscriptions": "0.1.
|
|
38
|
-
"@frigear-nu/ui": "0.1.
|
|
39
|
-
"@frigear-nu/auth": "0.1.
|
|
40
|
-
"@frigear-nu/mcp": "0.1.
|
|
41
|
-
"@frigear-nu/users": "1.1.
|
|
38
|
+
"@frigear-nu/admin": "0.1.3",
|
|
39
|
+
"@frigear-nu/module-kit": "1.1.3",
|
|
40
|
+
"@frigear-nu/payments": "0.1.3",
|
|
41
|
+
"@frigear-nu/stripe": "0.1.3",
|
|
42
|
+
"@frigear-nu/subscriptions": "0.1.3",
|
|
43
|
+
"@frigear-nu/ui": "0.1.3",
|
|
44
|
+
"@frigear-nu/auth": "0.1.4",
|
|
45
|
+
"@frigear-nu/mcp": "0.1.3",
|
|
46
|
+
"@frigear-nu/users": "1.1.4",
|
|
42
47
|
"@libsql/client": "^0.18.0",
|
|
43
48
|
"@nuxt/kit": "^4.6.1",
|
|
44
49
|
"@vueuse/core": "^15.0.0",
|
|
@@ -51,9 +56,9 @@
|
|
|
51
56
|
"zod": "^4.6.5"
|
|
52
57
|
},
|
|
53
58
|
"peerDependencies": {
|
|
54
|
-
"@frigear-nu/menu": "0.1.
|
|
55
|
-
"@frigear-nu/widget": "0.1.
|
|
56
|
-
"@nuxt/ui": "^4.
|
|
59
|
+
"@frigear-nu/menu": "0.1.3",
|
|
60
|
+
"@frigear-nu/widget": "0.1.3",
|
|
61
|
+
"@nuxt/ui": "^4.12.0",
|
|
57
62
|
"@nuxthub/core": "^0.10.8"
|
|
58
63
|
},
|
|
59
64
|
"peerDependenciesMeta": {
|
|
@@ -68,14 +73,14 @@
|
|
|
68
73
|
}
|
|
69
74
|
},
|
|
70
75
|
"devDependencies": {
|
|
71
|
-
"@frigear-nu/menu": "0.1.
|
|
72
|
-
"@frigear-nu/widget": "0.1.
|
|
76
|
+
"@frigear-nu/menu": "0.1.3",
|
|
77
|
+
"@frigear-nu/widget": "0.1.3",
|
|
73
78
|
"@nuxt/devtools": "^3.4.2",
|
|
74
79
|
"@nuxt/eslint-config": "^1.17.0",
|
|
75
80
|
"@nuxt/module-builder": "^1.0.3",
|
|
76
81
|
"@nuxt/schema": "^4.6.1",
|
|
77
82
|
"@nuxt/test-utils": "^4.3.2",
|
|
78
|
-
"@nuxt/ui": "^4.
|
|
83
|
+
"@nuxt/ui": "^4.12.0",
|
|
79
84
|
"@nuxthub/core": "^0.10.8",
|
|
80
85
|
"@types/node": "^26.6.5",
|
|
81
86
|
"changelogen": "^0.6.2",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { StaffAddon, StaffAddonGroup } from '../utils/admin-event.js';
|
|
2
|
-
declare function open(addonGroup: StaffAddonGroup, currency: string, existing?: StaffAddon): void;
|
|
3
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {
|
|
4
|
-
open: typeof open;
|
|
5
|
-
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
-
refresh: () => any;
|
|
7
|
-
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
8
|
-
onRefresh?: (() => any) | undefined;
|
|
9
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
10
|
-
declare const _default: typeof __VLS_export;
|
|
11
|
-
export default _default;
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { fromCents, toCents } from "@frigear-nu/ui/money";
|
|
3
|
-
import { DEFAULT_CURRENCY } from "../../utils";
|
|
4
|
-
defineOptions({ name: "EventAdminAddonDialog" });
|
|
5
|
-
const emit = defineEmits(["refresh"]);
|
|
6
|
-
const t = useModuleT("events");
|
|
7
|
-
const tr = useEventsTranslate();
|
|
8
|
-
const { busy, run } = useAction();
|
|
9
|
-
const dialog = ref(false);
|
|
10
|
-
const groupId = ref("");
|
|
11
|
-
const editingAddon = ref(null);
|
|
12
|
-
const addon = reactive({ label: void 0, description: void 0, price: 0, capacity: "" });
|
|
13
|
-
const addonCurrency = ref(DEFAULT_CURRENCY);
|
|
14
|
-
function open(addonGroup, currency, existing) {
|
|
15
|
-
groupId.value = addonGroup.id;
|
|
16
|
-
addonCurrency.value = currency;
|
|
17
|
-
editingAddon.value = existing ?? null;
|
|
18
|
-
Object.assign(addon, {
|
|
19
|
-
label: existing?.label,
|
|
20
|
-
description: existing?.description ?? void 0,
|
|
21
|
-
price: existing ? fromCents(existing.price, currency) : 0,
|
|
22
|
-
capacity: existing?.capacity ?? ""
|
|
23
|
-
});
|
|
24
|
-
dialog.value = true;
|
|
25
|
-
}
|
|
26
|
-
defineExpose({ open });
|
|
27
|
-
const save = () => run(async () => {
|
|
28
|
-
const body = {
|
|
29
|
-
label: addon.label,
|
|
30
|
-
description: addon.description ?? null,
|
|
31
|
-
// Prices are stored in minor units (øre/cents).
|
|
32
|
-
price: toCents(Number(addon.price), addonCurrency.value),
|
|
33
|
-
capacity: addon.capacity === "" ? null : Number(addon.capacity)
|
|
34
|
-
};
|
|
35
|
-
if (editingAddon.value) {
|
|
36
|
-
await $fetch(`/api/events/admin/addons/${editingAddon.value.id}`, { method: "PATCH", body });
|
|
37
|
-
} else {
|
|
38
|
-
await $fetch(`/api/events/admin/addon-groups/${groupId.value}/addons`, { method: "POST", body });
|
|
39
|
-
}
|
|
40
|
-
dialog.value = false;
|
|
41
|
-
emit("refresh");
|
|
42
|
-
}, { success: t("admin.addonSaved", "Add-on saved.") });
|
|
43
|
-
</script>
|
|
44
|
-
|
|
45
|
-
<template>
|
|
46
|
-
<UModal
|
|
47
|
-
v-model:open="dialog"
|
|
48
|
-
:title="editingAddon ? t('admin.editAddon', 'Edit choice') : t('admin.addAddon', 'Add choice')"
|
|
49
|
-
>
|
|
50
|
-
<template #body>
|
|
51
|
-
<form
|
|
52
|
-
id="admin-addon-form"
|
|
53
|
-
class="flex flex-col gap-4"
|
|
54
|
-
@submit.prevent="save"
|
|
55
|
-
>
|
|
56
|
-
<UFormField :label="t('admin.name', 'Name')">
|
|
57
|
-
<TranslatedInput
|
|
58
|
-
v-model="addon.label"
|
|
59
|
-
required
|
|
60
|
-
/>
|
|
61
|
-
</UFormField>
|
|
62
|
-
<UFormField :label="t('admin.description', 'Description')">
|
|
63
|
-
<TranslatedInput
|
|
64
|
-
v-model="addon.description"
|
|
65
|
-
multiline
|
|
66
|
-
:rows="2"
|
|
67
|
-
/>
|
|
68
|
-
</UFormField>
|
|
69
|
-
<UFormField
|
|
70
|
-
:label="t('admin.price', 'Price')"
|
|
71
|
-
:description="t('admin.addonPriceHelp', 'Added to the ticket price. 0 means included.')"
|
|
72
|
-
>
|
|
73
|
-
<UInput
|
|
74
|
-
v-model="addon.price"
|
|
75
|
-
type="number"
|
|
76
|
-
min="0"
|
|
77
|
-
step="0.01"
|
|
78
|
-
class="w-full"
|
|
79
|
-
/>
|
|
80
|
-
</UFormField>
|
|
81
|
-
<UFormField
|
|
82
|
-
:label="t('admin.capacity', 'Capacity')"
|
|
83
|
-
:description="t('admin.capacityHelp', 'Leave empty for unlimited.')"
|
|
84
|
-
>
|
|
85
|
-
<UInput
|
|
86
|
-
v-model="addon.capacity"
|
|
87
|
-
type="number"
|
|
88
|
-
min="0"
|
|
89
|
-
class="w-full"
|
|
90
|
-
/>
|
|
91
|
-
</UFormField>
|
|
92
|
-
</form>
|
|
93
|
-
</template>
|
|
94
|
-
<template #footer>
|
|
95
|
-
<div class="flex w-full justify-end gap-2">
|
|
96
|
-
<UButton
|
|
97
|
-
variant="outline"
|
|
98
|
-
color="neutral"
|
|
99
|
-
:label="t('admin.cancel', 'Cancel')"
|
|
100
|
-
@click="dialog = false"
|
|
101
|
-
/>
|
|
102
|
-
<UButton
|
|
103
|
-
type="submit"
|
|
104
|
-
form="admin-addon-form"
|
|
105
|
-
:loading="busy"
|
|
106
|
-
:disabled="!tr(addon.label)"
|
|
107
|
-
:label="t('admin.save', 'Save')"
|
|
108
|
-
/>
|
|
109
|
-
</div>
|
|
110
|
-
</template>
|
|
111
|
-
</UModal>
|
|
112
|
-
</template>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { StaffAddon, StaffAddonGroup } from '../utils/admin-event.js';
|
|
2
|
-
declare function open(addonGroup: StaffAddonGroup, currency: string, existing?: StaffAddon): void;
|
|
3
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {
|
|
4
|
-
open: typeof open;
|
|
5
|
-
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
-
refresh: () => any;
|
|
7
|
-
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
8
|
-
onRefresh?: (() => any) | undefined;
|
|
9
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
10
|
-
declare const _default: typeof __VLS_export;
|
|
11
|
-
export default _default;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { StaffAddonGroup, StaffTicketType } from '../utils/admin-event.js';
|
|
2
|
-
declare function open(ticketType: StaffTicketType, existing?: StaffAddonGroup): void;
|
|
3
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {
|
|
4
|
-
open: typeof open;
|
|
5
|
-
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
-
refresh: () => any;
|
|
7
|
-
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
8
|
-
onRefresh?: (() => any) | undefined;
|
|
9
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
10
|
-
declare const _default: typeof __VLS_export;
|
|
11
|
-
export default _default;
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
defineOptions({ name: "EventAdminAddonGroupDialog" });
|
|
3
|
-
const emit = defineEmits(["refresh"]);
|
|
4
|
-
const t = useModuleT("events");
|
|
5
|
-
const tr = useEventsTranslate();
|
|
6
|
-
const { busy, run } = useAction();
|
|
7
|
-
const dialog = ref(false);
|
|
8
|
-
const ticketTypeId = ref("");
|
|
9
|
-
const editingGroup = ref(null);
|
|
10
|
-
const group = reactive({ title: void 0, required: false, multiple: false });
|
|
11
|
-
function open(ticketType, existing) {
|
|
12
|
-
ticketTypeId.value = ticketType.id;
|
|
13
|
-
editingGroup.value = existing ?? null;
|
|
14
|
-
Object.assign(group, { title: existing?.title, required: existing?.required ?? false, multiple: existing?.multiple ?? false });
|
|
15
|
-
dialog.value = true;
|
|
16
|
-
}
|
|
17
|
-
defineExpose({ open });
|
|
18
|
-
const save = () => run(async () => {
|
|
19
|
-
const body = { title: group.title, required: group.required, multiple: group.multiple };
|
|
20
|
-
if (editingGroup.value) {
|
|
21
|
-
await $fetch(`/api/events/admin/addon-groups/${editingGroup.value.id}`, { method: "PATCH", body });
|
|
22
|
-
} else {
|
|
23
|
-
await $fetch(`/api/events/admin/ticket-types/${ticketTypeId.value}/addon-groups`, { method: "POST", body });
|
|
24
|
-
}
|
|
25
|
-
dialog.value = false;
|
|
26
|
-
emit("refresh");
|
|
27
|
-
}, { success: t("admin.groupSaved", "Add-on group saved.") });
|
|
28
|
-
</script>
|
|
29
|
-
|
|
30
|
-
<template>
|
|
31
|
-
<UModal
|
|
32
|
-
v-model:open="dialog"
|
|
33
|
-
:title="editingGroup ? t('admin.editGroup', 'Edit add-on group') : t('admin.addGroup', 'Add add-on group')"
|
|
34
|
-
>
|
|
35
|
-
<template #body>
|
|
36
|
-
<form
|
|
37
|
-
id="admin-addon-group-form"
|
|
38
|
-
class="flex flex-col gap-4"
|
|
39
|
-
@submit.prevent="save"
|
|
40
|
-
>
|
|
41
|
-
<UFormField
|
|
42
|
-
:label="t('admin.groupTitle', 'Title')"
|
|
43
|
-
:description="t('admin.groupTitleHelp', 'Shown above the choices, e.g. Food.')"
|
|
44
|
-
>
|
|
45
|
-
<TranslatedInput
|
|
46
|
-
v-model="group.title"
|
|
47
|
-
required
|
|
48
|
-
/>
|
|
49
|
-
</UFormField>
|
|
50
|
-
<UCheckbox
|
|
51
|
-
v-model="group.required"
|
|
52
|
-
:label="t('admin.groupRequiredLabel', 'Buyers must choose at least one')"
|
|
53
|
-
/>
|
|
54
|
-
<UCheckbox
|
|
55
|
-
v-model="group.multiple"
|
|
56
|
-
:label="t('admin.groupMultipleLabel', 'Buyers can choose several')"
|
|
57
|
-
/>
|
|
58
|
-
</form>
|
|
59
|
-
</template>
|
|
60
|
-
<template #footer>
|
|
61
|
-
<div class="flex w-full justify-end gap-2">
|
|
62
|
-
<UButton
|
|
63
|
-
variant="outline"
|
|
64
|
-
color="neutral"
|
|
65
|
-
:label="t('admin.cancel', 'Cancel')"
|
|
66
|
-
@click="dialog = false"
|
|
67
|
-
/>
|
|
68
|
-
<UButton
|
|
69
|
-
type="submit"
|
|
70
|
-
form="admin-addon-group-form"
|
|
71
|
-
:loading="busy"
|
|
72
|
-
:disabled="!tr(group.title)"
|
|
73
|
-
:label="t('admin.save', 'Save')"
|
|
74
|
-
/>
|
|
75
|
-
</div>
|
|
76
|
-
</template>
|
|
77
|
-
</UModal>
|
|
78
|
-
</template>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { StaffAddonGroup, StaffTicketType } from '../utils/admin-event.js';
|
|
2
|
-
declare function open(ticketType: StaffTicketType, existing?: StaffAddonGroup): void;
|
|
3
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {
|
|
4
|
-
open: typeof open;
|
|
5
|
-
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
-
refresh: () => any;
|
|
7
|
-
}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
|
|
8
|
-
onRefresh?: (() => any) | undefined;
|
|
9
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
10
|
-
declare const _default: typeof __VLS_export;
|
|
11
|
-
export default _default;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { StaffTicketType } from '../utils/admin-event.js';
|
|
2
|
-
type __VLS_Props = {
|
|
3
|
-
eventId: string;
|
|
4
|
-
/** Membership rules are only offered when @frigear-nu/subscriptions is installed. */
|
|
5
|
-
membershipEnabled: boolean;
|
|
6
|
-
plans: Array<{
|
|
7
|
-
label: string;
|
|
8
|
-
value: string;
|
|
9
|
-
}>;
|
|
10
|
-
};
|
|
11
|
-
declare function open(ticketType?: StaffTicketType): void;
|
|
12
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
13
|
-
open: typeof open;
|
|
14
|
-
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
15
|
-
refresh: () => any;
|
|
16
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
17
|
-
onRefresh?: (() => any) | undefined;
|
|
18
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
19
|
-
declare const _default: typeof __VLS_export;
|
|
20
|
-
export default _default;
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { toCents, fromCents } from "@frigear-nu/ui/money";
|
|
3
|
-
import { DEFAULT_CURRENCY, ticketMdcData } from "../../utils";
|
|
4
|
-
defineOptions({ name: "EventAdminTicketTypeDialog" });
|
|
5
|
-
const props = defineProps({
|
|
6
|
-
eventId: { type: String, required: true },
|
|
7
|
-
membershipEnabled: { type: Boolean, required: true },
|
|
8
|
-
plans: { type: Array, required: true }
|
|
9
|
-
});
|
|
10
|
-
const emit = defineEmits(["refresh"]);
|
|
11
|
-
const t = useModuleT("events");
|
|
12
|
-
const locale = useEventsLocale();
|
|
13
|
-
const tr = useEventsTranslate();
|
|
14
|
-
const { busy, run } = useAction();
|
|
15
|
-
const modes = computed(() => [
|
|
16
|
-
{ label: t("admin.ruleNone", "Nobody"), value: "none" },
|
|
17
|
-
{ label: t("admin.ruleAny", "Any membership"), value: "any" },
|
|
18
|
-
{ label: t("admin.rulePlans", "Specific memberships"), value: "plans" }
|
|
19
|
-
]);
|
|
20
|
-
const toRule = (value) => value === "any" ? { mode: "any", plans: [] } : Array.isArray(value) && value.length ? { mode: "plans", plans: [...value] } : { mode: "none", plans: [] };
|
|
21
|
-
const fromRule = (rule) => rule.mode === "any" ? "any" : rule.mode === "plans" && rule.plans.length ? [...rule.plans] : null;
|
|
22
|
-
const dialog = ref(false);
|
|
23
|
-
const editingType = ref(null);
|
|
24
|
-
const type = reactive({ key: "", name: void 0, description: void 0, price: 0, capacity: "", requires: toRule(null), excludes: toRule(null) });
|
|
25
|
-
function open(ticketType) {
|
|
26
|
-
editingType.value = ticketType ?? null;
|
|
27
|
-
Object.assign(type, {
|
|
28
|
-
key: ticketType?.key ?? "",
|
|
29
|
-
name: ticketType?.name,
|
|
30
|
-
description: ticketType?.description ?? void 0,
|
|
31
|
-
price: ticketType ? fromCents(ticketType.price, ticketType.currency) : 0,
|
|
32
|
-
capacity: ticketType?.capacity ?? "",
|
|
33
|
-
requires: toRule(ticketType?.requiresMembership),
|
|
34
|
-
excludes: toRule(ticketType?.excludesMembership)
|
|
35
|
-
});
|
|
36
|
-
dialog.value = true;
|
|
37
|
-
}
|
|
38
|
-
defineExpose({ open });
|
|
39
|
-
const save = () => run(async () => {
|
|
40
|
-
const body = {
|
|
41
|
-
name: type.name,
|
|
42
|
-
description: type.description ?? null,
|
|
43
|
-
// Prices are stored in minor units (øre/cents).
|
|
44
|
-
price: toCents(Number(type.price), editingType.value?.currency ?? DEFAULT_CURRENCY),
|
|
45
|
-
capacity: type.capacity === "" ? null : Number(type.capacity),
|
|
46
|
-
...props.membershipEnabled ? { requiresMembership: fromRule(type.requires), excludesMembership: fromRule(type.excludes) } : {}
|
|
47
|
-
};
|
|
48
|
-
if (editingType.value) {
|
|
49
|
-
await $fetch(`/api/events/admin/ticket-types/${editingType.value.id}`, { method: "PATCH", body });
|
|
50
|
-
} else {
|
|
51
|
-
await $fetch(`/api/events/admin/events/${props.eventId}/ticket-types`, { method: "POST", body: { key: type.key, ...body } });
|
|
52
|
-
}
|
|
53
|
-
dialog.value = false;
|
|
54
|
-
emit("refresh");
|
|
55
|
-
}, { success: t("admin.typeSaved", "Ticket type saved.") });
|
|
56
|
-
</script>
|
|
57
|
-
|
|
58
|
-
<template>
|
|
59
|
-
<UModal
|
|
60
|
-
v-model:open="dialog"
|
|
61
|
-
:title="editingType ? t('admin.editType', 'Edit ticket type') : t('admin.addType', 'Add ticket type')"
|
|
62
|
-
>
|
|
63
|
-
<template #body>
|
|
64
|
-
<form
|
|
65
|
-
id="admin-ticket-type-form"
|
|
66
|
-
class="flex flex-col gap-4"
|
|
67
|
-
@submit.prevent="save"
|
|
68
|
-
>
|
|
69
|
-
<UFormField :label="t('admin.name', 'Name')">
|
|
70
|
-
<TranslatedInput
|
|
71
|
-
v-model="type.name"
|
|
72
|
-
required
|
|
73
|
-
/>
|
|
74
|
-
</UFormField>
|
|
75
|
-
<UFormField :label="t('admin.description', 'Description')">
|
|
76
|
-
<TranslatedInput
|
|
77
|
-
v-model="type.description"
|
|
78
|
-
multiline
|
|
79
|
-
mdc
|
|
80
|
-
:mdc-data="ticketMdcData({ ...type, price: toCents(Number(type.price), editingType?.currency ?? DEFAULT_CURRENCY), currency: editingType?.currency ?? DEFAULT_CURRENCY }, tr(type.name), locale)"
|
|
81
|
-
:rows="2"
|
|
82
|
-
/>
|
|
83
|
-
</UFormField>
|
|
84
|
-
<UFormField
|
|
85
|
-
v-if="!editingType"
|
|
86
|
-
:label="t('admin.key', 'Key')"
|
|
87
|
-
:description="t('admin.keyHelp', 'A short unique id, e.g. member.')"
|
|
88
|
-
>
|
|
89
|
-
<UInput
|
|
90
|
-
v-model="type.key"
|
|
91
|
-
class="w-full"
|
|
92
|
-
required
|
|
93
|
-
/>
|
|
94
|
-
</UFormField>
|
|
95
|
-
<UFormField :label="t('admin.price', 'Price')">
|
|
96
|
-
<UInput
|
|
97
|
-
v-model="type.price"
|
|
98
|
-
type="number"
|
|
99
|
-
min="0"
|
|
100
|
-
step="0.01"
|
|
101
|
-
class="w-full"
|
|
102
|
-
/>
|
|
103
|
-
</UFormField>
|
|
104
|
-
<UFormField
|
|
105
|
-
:label="t('admin.capacity', 'Capacity')"
|
|
106
|
-
:description="t('admin.capacityHelp', 'Leave empty for unlimited.')"
|
|
107
|
-
>
|
|
108
|
-
<UInput
|
|
109
|
-
v-model="type.capacity"
|
|
110
|
-
type="number"
|
|
111
|
-
min="0"
|
|
112
|
-
class="w-full"
|
|
113
|
-
/>
|
|
114
|
-
</UFormField>
|
|
115
|
-
|
|
116
|
-
<template v-if="membershipEnabled">
|
|
117
|
-
<UFormField
|
|
118
|
-
:label="t('admin.requiresMembership', 'Only for members of')"
|
|
119
|
-
:description="t('admin.requiresHelp', 'Visitors without a matching active membership cannot buy this ticket.')"
|
|
120
|
-
>
|
|
121
|
-
<USelect
|
|
122
|
-
v-model="type.requires.mode"
|
|
123
|
-
:items="modes"
|
|
124
|
-
class="w-full"
|
|
125
|
-
/>
|
|
126
|
-
<USelectMenu
|
|
127
|
-
v-if="type.requires.mode === 'plans'"
|
|
128
|
-
v-model="type.requires.plans"
|
|
129
|
-
:items="plans"
|
|
130
|
-
value-key="value"
|
|
131
|
-
multiple
|
|
132
|
-
class="mt-2 w-full"
|
|
133
|
-
/>
|
|
134
|
-
</UFormField>
|
|
135
|
-
<UFormField
|
|
136
|
-
:label="t('admin.excludesMembership', 'Not for members of')"
|
|
137
|
-
:description="t('admin.excludesHelp', 'Holders of these memberships cannot buy this ticket, so members and non-members can have separate prices.')"
|
|
138
|
-
>
|
|
139
|
-
<USelect
|
|
140
|
-
v-model="type.excludes.mode"
|
|
141
|
-
:items="modes"
|
|
142
|
-
class="w-full"
|
|
143
|
-
/>
|
|
144
|
-
<USelectMenu
|
|
145
|
-
v-if="type.excludes.mode === 'plans'"
|
|
146
|
-
v-model="type.excludes.plans"
|
|
147
|
-
:items="plans"
|
|
148
|
-
value-key="value"
|
|
149
|
-
multiple
|
|
150
|
-
class="mt-2 w-full"
|
|
151
|
-
/>
|
|
152
|
-
</UFormField>
|
|
153
|
-
</template>
|
|
154
|
-
</form>
|
|
155
|
-
</template>
|
|
156
|
-
<template #footer>
|
|
157
|
-
<div class="flex w-full justify-end gap-2">
|
|
158
|
-
<UButton
|
|
159
|
-
variant="outline"
|
|
160
|
-
color="neutral"
|
|
161
|
-
:label="t('admin.cancel', 'Cancel')"
|
|
162
|
-
@click="dialog = false"
|
|
163
|
-
/>
|
|
164
|
-
<UButton
|
|
165
|
-
type="submit"
|
|
166
|
-
form="admin-ticket-type-form"
|
|
167
|
-
:loading="busy"
|
|
168
|
-
:disabled="!tr(type.name)"
|
|
169
|
-
:label="t('admin.save', 'Save')"
|
|
170
|
-
/>
|
|
171
|
-
</div>
|
|
172
|
-
</template>
|
|
173
|
-
</UModal>
|
|
174
|
-
</template>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { StaffTicketType } from '../utils/admin-event.js';
|
|
2
|
-
type __VLS_Props = {
|
|
3
|
-
eventId: string;
|
|
4
|
-
/** Membership rules are only offered when @frigear-nu/subscriptions is installed. */
|
|
5
|
-
membershipEnabled: boolean;
|
|
6
|
-
plans: Array<{
|
|
7
|
-
label: string;
|
|
8
|
-
value: string;
|
|
9
|
-
}>;
|
|
10
|
-
};
|
|
11
|
-
declare function open(ticketType?: StaffTicketType): void;
|
|
12
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
13
|
-
open: typeof open;
|
|
14
|
-
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
15
|
-
refresh: () => any;
|
|
16
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
17
|
-
onRefresh?: (() => any) | undefined;
|
|
18
|
-
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
19
|
-
declare const _default: typeof __VLS_export;
|
|
20
|
-
export default _default;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { db, schema } from "@nuxthub/db";
|
|
2
|
-
import { and, eq } from "drizzle-orm";
|
|
3
|
-
export default defineEventHandler(async (event) => {
|
|
4
|
-
const user = await requireUser(event, { scopes: ["tickets:write"] });
|
|
5
|
-
const [ticket] = await db.select().from(schema.eventTickets).where(and(eq(schema.eventTickets.id, getRouterParam(event, "id")), eq(schema.eventTickets.userId, user.id))).limit(1);
|
|
6
|
-
if (!ticket) throw createError({ statusCode: 404, statusMessage: "Ticket not found." });
|
|
7
|
-
if (ticket.status === "paid") throw createError({ statusCode: 409, statusMessage: "This ticket is already paid." });
|
|
8
|
-
if (ticket.status !== "pending" || !ticket.paymentId) throw createError({ statusCode: 409, statusMessage: "This ticket can no longer be paid. Buy a new one." });
|
|
9
|
-
return resumePayment(ticket.paymentId, user.id, event);
|
|
10
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|