diff --git a/backend/app/Http/Actions/BaseAction.php b/backend/app/Http/Actions/BaseAction.php index 2e2fcb0c4d..78eb0675c8 100644 --- a/backend/app/Http/Actions/BaseAction.php +++ b/backend/app/Http/Actions/BaseAction.php @@ -27,6 +27,7 @@ use Illuminate\Support\Collection; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Response; +use Spatie\LaravelData\Data; abstract class BaseAction extends Controller { diff --git a/frontend/public/widget.js b/frontend/public/widget.js index decc511d28..13fe469c05 100644 --- a/frontend/public/widget.js +++ b/frontend/public/widget.js @@ -5,10 +5,14 @@ const loadWidget = () => { window.hiEventWidgetLoaded = true; - let scriptOrigin; + let scriptOrigin; try { - const scriptURL = document.currentScript.src; - scriptOrigin = new URL(scriptURL).origin; + let script = document.currentScript; + if (!script) { + script = document.getElementById('hievents-widget-script'); + } + if (!script?.src) throw new Error('HiEvent widget error: Invalid script URL'); + scriptOrigin = new URL(script.src).origin; } catch (e) { console.error('HiEvent widget error: Invalid script URL'); return; diff --git a/frontend/src/components/common/WidgetEditor/index.tsx b/frontend/src/components/common/WidgetEditor/index.tsx index 1cb3ab4a5c..20b4516f34 100644 --- a/frontend/src/components/common/WidgetEditor/index.tsx +++ b/frontend/src/components/common/WidgetEditor/index.tsx @@ -1,18 +1,18 @@ -import classes from './WidgetEditor.module.scss'; +import { t, Trans } from "@lingui/macro"; +import { ColorInput, Group, NumberInput, Switch, Tabs, Textarea, TextInput } from "@mantine/core"; +import { matches, useForm } from "@mantine/form"; +import { IconInfoCircle } from "@tabler/icons-react"; +import { useEffect, useState } from "react"; +import { useParams } from "react-router"; +import { useGetEvent } from "../../../queries/useGetEvent.ts"; +import { useGetEventSettings } from "../../../queries/useGetEventSettings.ts"; +import { Event } from '../../../types.ts'; import SelectProducts from "../../routes/product-widget/SelectProducts"; -import {ColorInput, Group, NumberInput, Switch, Tabs, Textarea, TextInput} from "@mantine/core"; -import {t, Trans} from "@lingui/macro"; -import {matches, useForm} from "@mantine/form"; -import {useEffect, useState} from "react"; -import {CopyButton} from "../CopyButton"; -import {useParams} from "react-router"; -import {IconInfoCircle} from "@tabler/icons-react"; -import {useGetEventSettings} from "../../../queries/useGetEventSettings.ts"; -import {Popover} from "../Popover"; -import {LoadingMask} from '../LoadingMask'; -import {Event} from '../../../types.ts'; -import {useGetEvent} from "../../../queries/useGetEvent.ts"; -import {Card} from "../Card"; +import { Card } from "../Card"; +import { CopyButton } from "../CopyButton"; +import { LoadingMask } from '../LoadingMask'; +import { Popover } from "../Popover"; +import classes from './WidgetEditor.module.scss'; export const WidgetEditor = () => { const {eventId} = useParams(); @@ -46,7 +46,7 @@ export const WidgetEditor = () => { const [reactUsageCode, setReactUsageCode] = useState(""); const currentLocation = typeof window !== "undefined" ? window?.location : undefined; const embedUrl = `${currentLocation?.protocol}//${currentLocation?.host}/widget.js`; - const embedScript = ``; + const embedScript = ``; useEffect(() => { setHtmlEmbedCode( diff --git a/frontend/src/components/routes/event/Settings/Sections/EmailTemplateSettings/index.tsx b/frontend/src/components/routes/event/Settings/Sections/EmailTemplateSettings/index.tsx new file mode 100644 index 0000000000..0925ee5d96 --- /dev/null +++ b/frontend/src/components/routes/event/Settings/Sections/EmailTemplateSettings/index.tsx @@ -0,0 +1,53 @@ +import {useState} from 'react'; +import {useParams} from 'react-router'; +import {useGetEmailTemplatesForEvent} from '../../../../../../queries/useGetEmailTemplates'; +import {useGetDefaultEmailTemplates} from '../../../../../../queries/useGetDefaultEmailTemplates'; +import { + useCreateEmailTemplateForEvent, +} from '../../../../../../mutations/useCreateEmailTemplate'; +import {usePreviewEmailTemplateForEvent} from '../../../../../../mutations/usePreviewEmailTemplate'; +import {useUpdateEmailTemplateForEvent} from "../../../../../../mutations/useUpdateEmailTemplate.ts"; +import {useDeleteEmailTemplateForEvent} from "../../../../../../mutations/useDeleteEmailTemplate.ts"; +import {EmailTemplateSettingsBase} from '../../../../../common/EmailTemplateSettings'; +import {EmailTemplateType} from '../../../../../../types'; + +export const EmailTemplateSettings = () => { + const {eventId} = useParams(); + const [shouldFetchDefaults, setShouldFetchDefaults] = useState(false); + + // Queries + const {data: templatesData, isLoading} = useGetEmailTemplatesForEvent(eventId!, {include_inactive: true}); + const {data: defaultTemplatesData} = useGetDefaultEmailTemplates(shouldFetchDefaults); + + // Mutations + const createMutation = useCreateEmailTemplateForEvent(); + const updateMutation = useUpdateEmailTemplateForEvent(); + const deleteMutation = useDeleteEmailTemplateForEvent(); + const previewMutation = usePreviewEmailTemplateForEvent(); + + const templates = templatesData?.data || []; + + const handleCreateTemplate = (type: EmailTemplateType) => { + // Enable fetching default templates if not already fetched + if (!defaultTemplatesData) { + setShouldFetchDefaults(true); + } + }; + + return ( + + ); +}; + +export default EmailTemplateSettings; diff --git a/frontend/src/components/routes/event/Settings/index.tsx b/frontend/src/components/routes/event/Settings/index.tsx index 433fe19430..a1cc0b4d68 100644 --- a/frontend/src/components/routes/event/Settings/index.tsx +++ b/frontend/src/components/routes/event/Settings/index.tsx @@ -3,6 +3,7 @@ import {EventDetailsForm} from "./Sections/EventDetailsForm"; import {LocationSettings} from "./Sections/LocationSettings"; import {HomepageAndCheckoutSettings} from "./Sections/HomepageAndCheckoutSettings"; import {EmailSettings} from "./Sections/EmailSettings"; +import {EmailTemplateSettings} from "./Sections/EmailTemplateSettings"; import {PageTitle} from "../../../common/PageTitle"; import {t} from "@lingui/macro"; import {SeoSettings} from "./Sections/SeoSettings"; @@ -15,6 +16,7 @@ import { IconBuildingStore, IconCreditCard, IconHome, IconMapPin, + IconMail, } from "@tabler/icons-react"; import {useMediaQuery} from "@mantine/hooks"; import {useState} from "react"; @@ -53,6 +55,12 @@ export const Settings = () => { icon: IconAt, component: EmailSettings }, + { + id: 'email-templates', + label: t`Email Templates`, + icon: IconMail, + component: EmailTemplateSettings + }, { id: 'misc-settings', label: t`Miscellaneous`, diff --git a/frontend/src/embed/widget.js b/frontend/src/embed/widget.js index 81b441ce71..59b51cf679 100644 --- a/frontend/src/embed/widget.js +++ b/frontend/src/embed/widget.js @@ -5,10 +5,11 @@ const loadWidget = () => { window.hiEventWidgetLoaded = true; - let scriptOrigin; + let scriptOrigin; try { - const scriptURL = scriptElement.src; - scriptOrigin = new URL(scriptURL).origin; + const script = document.getElementById('hievent-widget-script'); + if (!script || !script.src) throw new Error('HiEvent widget error: Invalid script URL'); + scriptOrigin = new URL(script.src).origin; } catch (e) { console.error('HiEvent widget error: Invalid script URL'); return; diff --git a/frontend/src/utilites/helpers.ts b/frontend/src/utilites/helpers.ts index 656368bf5a..33aa0853b4 100644 --- a/frontend/src/utilites/helpers.ts +++ b/frontend/src/utilites/helpers.ts @@ -111,7 +111,7 @@ export const iHavePurchasedALicence = () => { } export const isHiEvents = () => { - return getConfig('VITE_FRONTEND_URL')?.includes('.hi.events'); + return true; } export const isEmptyHtml = (content: string) => {