Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 28 additions & 21 deletions dashboard/src/components/AddOnPreferenceDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,39 +43,46 @@
</Dialog>
</template>

<script setup>
<script setup lang="ts">
import { ref, computed, watch } from "vue";
import { Dialog, Button, FormControl, createResource, toast } from "frappe-ui";
import type { EventTicket } from "@/types/Ticketing/EventTicket";
import type { TicketDetailsAddOn } from "@/pages/TicketDetails.vue";
import type { FrappeError } from "@/types/Frappe/FrappeError";

type TicketWithAddOns = EventTicket & { add_ons: TicketDetailsAddOn[] };

const props = withDefaults(
defineProps<{
modelValue?: boolean;
ticket: TicketWithAddOns;
}>(),
{
modelValue: false,
}
);

const props = defineProps({
modelValue: {
type: Boolean,
default: false,
},
ticket: {
type: Object,
required: true,
},
});

const emit = defineEmits(["update:modelValue", "success"]);
const emit = defineEmits<{
"update:modelValue": [value: boolean];
success: [];
}>();

const show = computed({
get: () => props.modelValue,
set: (value) => emit("update:modelValue", value),
set: (value: boolean) => emit("update:modelValue", value),
});

const preferences = ref({});
const preferences = ref<Record<string, string>>({});

// Filter add-ons that have selectable options
const addOnsWithOptions = computed(() => {
if (!props.ticket?.add_ons) return [];

return props.ticket.add_ons
.filter((addon) => addon.options && addon.options.length > 0)
.map((addon) => ({
.filter((addon: TicketDetailsAddOn) => addon.options && addon.options.length > 0)
.map((addon: TicketDetailsAddOn) => ({
...addon,
selectOptions: addon.options.map((option) => ({
selectOptions: addon.options.map((option: string) => ({
label: __(option),
value: option,
})),
Expand All @@ -93,12 +100,12 @@ const hasChanges = computed(() => {
const dialogOptions = {
title: "Update Add-on Preferences",
size: "lg",
};
} as const;

// Initialize preferences when dialog opens
watch(
() => props.modelValue,
(newValue) => {
(newValue: boolean) => {
if (newValue && addOnsWithOptions.value.length > 0) {
preferences.value = {};
for (const addon of addOnsWithOptions.value) {
Expand All @@ -116,7 +123,7 @@ const savePreferences = createResource({
emit("success");
show.value = false;
},
onError: (error) => {
onError: (error: FrappeError) => {
// Check if this is the specific error about change window closing
if (error?.message?.includes("change window has closed")) {
toast.error(
Expand Down
23 changes: 11 additions & 12 deletions dashboard/src/components/QRCodeExpandDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,18 @@
</Dialog>
</template>

<script setup>
<script setup lang="ts">
import { Dialog } from "frappe-ui";

const isOpen = defineModel({ type: Boolean, default: false });
const isOpen = defineModel<boolean>({ default: false });

defineProps({
qrCodeSrc: {
type: String,
required: true,
},
altText: {
type: String,
default: "QR Code",
},
});
withDefaults(
defineProps<{
qrCodeSrc: string;
altText?: string;
}>(),
{
altText: "QR Code",
}
);
</script>
35 changes: 20 additions & 15 deletions dashboard/src/components/TicketTransferDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,31 @@
</Dialog>
</template>

<script setup>
<script setup lang="ts">
import { ref, watch, computed } from "vue";
import { createResource, Dialog, FormControl, Button, toast } from "frappe-ui";
import type { EventTicket } from "@/types/Ticketing/EventTicket";
import { FrappeError } from "@/types/Frappe/FrappeError";

const props = defineProps({
modelValue: {
type: Boolean,
default: false,
},
ticket: {
type: Object,
default: null,
},
});
const props = withDefaults(
defineProps<{
modelValue?: boolean;
ticket?: EventTicket | null;
}>(),
{
modelValue: false,
ticket: null,
}
);

const emit = defineEmits(["update:modelValue", "success"]);
const emit = defineEmits<{
"update:modelValue": [value: boolean];
success: [];
}>();

const isOpen = computed({
get: () => props.modelValue,
set: (value) => emit("update:modelValue", value),
set: (value: boolean) => emit("update:modelValue", value),
});

const transferForm = ref({
Expand All @@ -82,7 +87,7 @@ const transferResource = createResource({
resetTransferForm();
emit("success");
},
onError: (error) => {
onError: (error: FrappeError) => {
toast.error(`${__("Failed to transfer ticket")}: ${error.message}`);
},
});
Expand All @@ -108,7 +113,7 @@ const resetTransferForm = () => {
};

// Reset form when dialog is closed
watch(isOpen, (newValue) => {
watch(isOpen, (newValue: boolean) => {
if (!newValue) {
resetTransferForm();
}
Expand Down
25 changes: 14 additions & 11 deletions dashboard/src/components/common/BackButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@
</Button>
</template>

<script setup>
defineProps({
to: {
type: [String, Object],
default: null,
},
label: {
type: String,
default: "Back",
},
<script setup lang="ts">
import type { RouteLocationRaw } from "vue-router";

interface Props {
to?: RouteLocationRaw | null;
label?: string;
}

withDefaults(defineProps<Props>(), {
to: null,
label: "Back",
});

defineEmits(["click"]);
defineEmits<{
(e: "click", event: MouseEvent): void;
}>();
</script>
21 changes: 21 additions & 0 deletions dashboard/src/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

declare module "*.wav" {
const value: string;
export default value;
}

declare module "*.mp3" {
const value: string;
export default value;
}

declare module "*.svg" {
const value: string;
export default value;
}

declare module "~icons/*" {
import type { DefineComponent } from "vue";
const component: DefineComponent<{}, {}, any>;
export default component;
}
17 changes: 4 additions & 13 deletions dashboard/src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,10 @@ declare global {
}

function __(str: string, values?: any[]): string;
}

declare module "*.wav" {
const value: string;
export default value;
}

declare module "*.mp3" {
const value: string;
export default value;
}

declare module "*.svg" {
const value: string;
export default value;
declare module "@vue/runtime-core" {
interface ComponentCustomProperties {
__(str: string, values?: any[]): string;
}
}
45 changes: 38 additions & 7 deletions dashboard/src/pages/TicketDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@
</div>
</template>

<script setup>
<script setup lang="ts">
import { ref, computed } from "vue";
import { createResource, Spinner, Button, Badge } from "frappe-ui";
import { formatCurrency } from "@/utils/currency";
Expand All @@ -341,6 +341,34 @@ import LucideEdit from "~icons/lucide/edit";
import LucideTriangleAlert from "~icons/lucide/triangle-alert";
import LucideExternalLink from "~icons/lucide/external-link";
import BackButton from "../components/common/BackButton.vue";
import type { EventTicket } from "@/types/Ticketing/EventTicket";
import type { BuzzEvent } from "@/types/Events/BuzzEvent";
import type { EventBooking } from "@/types/Ticketing/EventBooking";
import type { EventTicketType } from "@/types/Ticketing/EventTicketType";

export interface TicketDetailsAddOn {
id: string;
name: string;
title: string;
value: string;
price: number;
currency: string;
user_selects_option: boolean;
options: string[];
}

export interface TicketDetailsAPIResponse {
doc: EventTicket;
add_ons: TicketDetailsAddOn[];
event: BuzzEvent;
booking: EventBooking | null;
ticket_type: EventTicketType;
can_transfer_ticket: { can_transfer: boolean };
can_change_add_ons: { can_change_add_ons: boolean };
can_request_cancellation: { can_request_cancellation: boolean };
zoom_join_url: string | null;
zoom_webinar?: string;
}

const props = defineProps({
ticketId: {
Expand All @@ -350,7 +378,7 @@ const props = defineProps({
});

// Helper function to format date and time together
const formatEventDateTime = (date, time) => {
const formatEventDateTime = (date: string, time?: string) => {
if (!date) return "";

// Create a date object from the date string
Expand All @@ -377,7 +405,7 @@ const ticketDetails = createResource({
url: "buzz.api.get_ticket_details",
params: { ticket_id: props.ticketId },
auto: true,
transform(data) {
transform(data: TicketDetailsAPIResponse) {
if (!data) return null;

return {
Expand All @@ -387,7 +415,10 @@ const ticketDetails = createResource({
...data.doc,
formatted_amount:
data.booking && data.booking.total_amount !== 0
? formatCurrency(data.booking.total_amount, data.booking.currency || "USD")
? formatCurrency(
data.booking.total_amount ?? 0,
data.booking.currency || "USD"
)
: "FREE",
booking_status: data.booking
? data.booking.docstatus === 1
Expand All @@ -410,7 +441,7 @@ const ticketDetails = createResource({
),
event_title: data.event?.title || "",
venue: data.event?.venue || "",
description: data.event?.description || "",
description: data.event?.short_description || "",
ticket_type_title: data.ticket_type?.title || data.doc.ticket_type,
},
// Add-ons with proper titles
Expand Down Expand Up @@ -438,7 +469,7 @@ const hasCustomizableAddOns = computed(() => {
}

console.log("Add-ons data:", ticketDetails.data.add_ons);
const hasCustomizable = ticketDetails.data.add_ons.some((addon) => {
const hasCustomizable = ticketDetails.data.add_ons.some((addon: any) => {
console.log(
"Checking addon:",
addon,
Expand All @@ -459,7 +490,7 @@ const canChangeAddOns = computed(() => {
);
});

const getTicketStatusTheme = (status) => {
const getTicketStatusTheme = (status: string) => {
switch (status) {
case "Confirmed":
case "Active":
Expand Down
Loading
Loading