@frigear-nu/events 0.1.2 → 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 +35 -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.js +6 -6
- 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 +4 -0
- 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 +102 -139
- 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 +22 -3
- package/dist/runtime/i18n/lang/en.json +22 -3
- package/dist/runtime/server/bootstrap/my-tickets.d.ts +1 -1
- 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/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 +19 -14
- 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/dist/runtime/server/routes/{public/tickets-me.get.js → me/tickets.get.js} +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,8 +56,8 @@
|
|
|
51
56
|
"zod": "^4.6.5"
|
|
52
57
|
},
|
|
53
58
|
"peerDependencies": {
|
|
54
|
-
"@frigear-nu/menu": "0.1.
|
|
55
|
-
"@frigear-nu/widget": "0.1.
|
|
59
|
+
"@frigear-nu/menu": "0.1.3",
|
|
60
|
+
"@frigear-nu/widget": "0.1.3",
|
|
56
61
|
"@nuxt/ui": "^4.12.0",
|
|
57
62
|
"@nuxthub/core": "^0.10.8"
|
|
58
63
|
},
|
|
@@ -68,8 +73,8 @@
|
|
|
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",
|
|
@@ -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
|
|
File without changes
|