share calendar
parent
a819ab52bb
commit
d5148f8c48
|
@ -269,7 +269,19 @@
|
||||||
"checkboxDeleteCalendars": "Kalender für Öffnungszeiten und Termine löschen (Alle Termine werden gelöscht und können nicht wiederhergestellt werden)",
|
"checkboxDeleteCalendars": "Kalender für Öffnungszeiten und Termine löschen (Alle Termine werden gelöscht und können nicht wiederhergestellt werden)",
|
||||||
"button": "Google Kalender trennen"
|
"button": "Google Kalender trennen"
|
||||||
},
|
},
|
||||||
"calendarFrameCustomerView": "Terminkalenderansicht der Kunden"
|
"calendarFrameCustomerView": "Terminkalenderansicht der Kunden",
|
||||||
|
"modalShareCalendarLink": {
|
||||||
|
"title": "Kalender-Link teilen",
|
||||||
|
"shareButtons": {
|
||||||
|
"emailSubject": "Buchen Sie einen Termin bei uns",
|
||||||
|
"emailBody": "Hallo,\n\n nutzen Sie den folgenden Link, um unseren Kalender einzusehen und einen Termin zu buchen.\n\n{{link}}\n\nMit freundlichen Grüßen\n\n{{username}}",
|
||||||
|
"whatsAppBody": "Hallo, nutzen Sie den folgenden Link, um unseren Kalender einzusehen und einen Termin zu buchen.\n\n{{link}}\n\nMit freundlichen Grüßen\n\n{{username}}"
|
||||||
|
},
|
||||||
|
"info": "Geben Sie den folgenden Link an Ihre Kunden weiter, damit diese Ihren Kalender einsehen und Termine buchen können.",
|
||||||
|
"bookingPageLink": "Link zur Buchungsseite",
|
||||||
|
"embed": "Einbetten",
|
||||||
|
"embedInfo": "Binden Sie den Kalender mit folgendem Code in Ihre Website ein."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"storeSettings": {
|
"storeSettings": {
|
||||||
"pageTitle": "Einstellungen"
|
"pageTitle": "Einstellungen"
|
||||||
|
|
|
@ -272,7 +272,19 @@
|
||||||
"checkboxDeleteCalendars": "Delete calendar for opening hours and appointments (all appointments are deleted and cannot be restored)",
|
"checkboxDeleteCalendars": "Delete calendar for opening hours and appointments (all appointments are deleted and cannot be restored)",
|
||||||
"button": "Unlink Google Calendar"
|
"button": "Unlink Google Calendar"
|
||||||
},
|
},
|
||||||
"calendarFrameCustomerView": "Appointment diary view of customers"
|
"calendarFrameCustomerView": "Appointment diary view of customers",
|
||||||
|
"modalShareCalendarLink": {
|
||||||
|
"title": "Share calendar link",
|
||||||
|
"shareButtons": {
|
||||||
|
"emailSubject": "Book an appointment with us",
|
||||||
|
"emailBody": "Hello,\n\nuse the following link to view our calendar and book an appointment.\n\n{{link}}\n\nBest regards\n\n{{username}}",
|
||||||
|
"whatsAppBody": "Hello, use the following link to view our calendar and book an appointment:\n\n{{link}}\n\nBest regards\n\n{{username}}"
|
||||||
|
},
|
||||||
|
"info": "Share the following link with your customers to allow them to view your calendar and book appointments.",
|
||||||
|
"bookingPageLink": "Booking page link",
|
||||||
|
"embed": "Embed",
|
||||||
|
"embedInfo": "Embed the calendar on your website with the following code."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"storeSettings": {
|
"storeSettings": {
|
||||||
"pageTitle": "Settings"
|
"pageTitle": "Settings"
|
||||||
|
|
|
@ -2,8 +2,10 @@ import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
Col,
|
Col,
|
||||||
|
Flex,
|
||||||
Form,
|
Form,
|
||||||
Grid,
|
Grid,
|
||||||
|
QRCode,
|
||||||
Result,
|
Result,
|
||||||
Row,
|
Row,
|
||||||
Space,
|
Space,
|
||||||
|
@ -34,8 +36,17 @@ import {
|
||||||
} from "../../../Components/MyRequestStateItem";
|
} from "../../../Components/MyRequestStateItem";
|
||||||
import MyModal, {
|
import MyModal, {
|
||||||
MyModalCloseConfirmButtonFooter,
|
MyModalCloseConfirmButtonFooter,
|
||||||
|
MyModalOnlyCloseButtonFooter,
|
||||||
} from "../../../Components/MyModal";
|
} from "../../../Components/MyModal";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
import {
|
||||||
|
DownloadOutlined,
|
||||||
|
MailOutlined,
|
||||||
|
ShareAltOutlined,
|
||||||
|
WhatsAppOutlined,
|
||||||
|
} from "@ant-design/icons";
|
||||||
|
import Paragraph from "antd/es/typography/Paragraph";
|
||||||
|
import { useSideBarContext } from "../../../Contexts/SideBarContext";
|
||||||
|
|
||||||
const { useBreakpoint } = Grid;
|
const { useBreakpoint } = Grid;
|
||||||
|
|
||||||
|
@ -191,20 +202,22 @@ export default function StoreCalendar() {
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Col xs={24}>
|
<Col xs={24}>
|
||||||
<Card title={t("calendar.calendarFrameCustomerView")}>
|
<CalendarFrameCard storeId={storeId} />
|
||||||
<CalendarFrame storeId={storeId} />
|
|
||||||
</Card>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CalendarFrame({ storeId }) {
|
function CalendarFrameCard({ storeId }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Card
|
||||||
|
title={t("calendar.calendarFrameCustomerView")}
|
||||||
|
extra={<ModalShareCalendarLink storeId={storeId} />}
|
||||||
|
>
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
@ -225,6 +238,139 @@ function CalendarFrame({ storeId }) {
|
||||||
height={530}
|
height={530}
|
||||||
src={`${Constants.EMBED_CALENDAR_ADDRESS}${storeId}`}
|
src={`${Constants.EMBED_CALENDAR_ADDRESS}${storeId}`}
|
||||||
/>
|
/>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ModalShareCalendarLink({ storeId }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
|
const sideBarContext = useSideBarContext();
|
||||||
|
|
||||||
|
const handleModalClose = () => setIsModalOpen(false);
|
||||||
|
|
||||||
|
const embedPreContent = `<button onclick="KKInnovation.openPopup({url: '${Constants.EMBED_CALENDAR_ADDRESS}${storeId}'});">
|
||||||
|
Termin Buchen
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<script src="${Constants.EMBED_CALENDAR_SCRIPT_ADDRESS}" type="text/javascript" async></script>`;
|
||||||
|
|
||||||
|
const downloadQRCode = () => {
|
||||||
|
const canvas = document
|
||||||
|
.getElementById("calendar-qrcode")
|
||||||
|
?.querySelector("canvas");
|
||||||
|
if (canvas) {
|
||||||
|
const url = canvas.toDataURL();
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.download = "QRCode.png";
|
||||||
|
a.href = url;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ShareAltOutlined onClick={() => setIsModalOpen(true)} />
|
||||||
|
|
||||||
|
<MyModal
|
||||||
|
title={t("calendar.modalShareCalendarLink.title")}
|
||||||
|
isOpen={isModalOpen}
|
||||||
|
onCancel={handleModalClose}
|
||||||
|
footer={<MyModalOnlyCloseButtonFooter onCancel={handleModalClose} />}
|
||||||
|
>
|
||||||
|
<Space style={{ paddingBottom: 12 }}>
|
||||||
|
<MailOutlined
|
||||||
|
style={{ fontSize: 20 }}
|
||||||
|
onClick={() =>
|
||||||
|
window.open(
|
||||||
|
`mailto:?subject=${t(
|
||||||
|
"calendar.modalShareCalendarLink.shareButtons.emailSubject"
|
||||||
|
)}&body=${encodeURIComponent(
|
||||||
|
t("calendar.modalShareCalendarLink.shareButtons.emailBody", {
|
||||||
|
link: `<a href="${Constants.EMBED_CALENDAR_ADDRESS}${storeId}">${Constants.EMBED_CALENDAR_ADDRESS}${storeId}</a>`,
|
||||||
|
username: sideBarContext.username,
|
||||||
|
})
|
||||||
|
)}`,
|
||||||
|
"_self"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<WhatsAppOutlined
|
||||||
|
style={{ fontSize: 20 }}
|
||||||
|
onClick={() =>
|
||||||
|
window.open(
|
||||||
|
`https://web.whatsapp.com/send?text=${encodeURIComponent(
|
||||||
|
t(
|
||||||
|
"calendar.modalShareCalendarLink.shareButtons.whatsAppBody",
|
||||||
|
{
|
||||||
|
link: `${Constants.EMBED_CALENDAR_ADDRESS}${storeId}`,
|
||||||
|
username: sideBarContext.username,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="calendar-qrcode"
|
||||||
|
style={{ paddingBottom: 12 }}
|
||||||
|
onClick={downloadQRCode}
|
||||||
|
>
|
||||||
|
<QRCode
|
||||||
|
value={`${Constants.EMBED_CALENDAR_ADDRESS}${storeId}`}
|
||||||
|
bgColor="#fff"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Flex vertical>
|
||||||
|
<Typography.Text strong>
|
||||||
|
{t("calendar.modalShareCalendarLink.info")}
|
||||||
|
</Typography.Text>
|
||||||
|
|
||||||
|
<Paragraph
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 12,
|
||||||
|
}}
|
||||||
|
copyable={{
|
||||||
|
text: `${Constants.EMBED_CALENDAR_ADDRESS}${storeId}`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<pre style={{ flex: 1 }}>
|
||||||
|
{`${Constants.EMBED_CALENDAR_ADDRESS}${storeId}`}
|
||||||
|
</pre>
|
||||||
|
</Paragraph>
|
||||||
|
|
||||||
|
<Typography.Text strong>
|
||||||
|
{t("calendar.modalShareCalendarLink.embed")}
|
||||||
|
</Typography.Text>
|
||||||
|
|
||||||
|
<Typography.Text>
|
||||||
|
{t("calendar.modalShareCalendarLink.embedInfo")}
|
||||||
|
</Typography.Text>
|
||||||
|
|
||||||
|
<Paragraph
|
||||||
|
copyable={{
|
||||||
|
text: embedPreContent,
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 12,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<pre style={{ flex: 1 }}>{embedPreContent}</pre>
|
||||||
|
</Paragraph>
|
||||||
|
</Flex>
|
||||||
|
</MyModal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -301,7 +447,7 @@ function CardPersonalCalendarSettings({ settings }) {
|
||||||
t: t,
|
t: t,
|
||||||
})
|
})
|
||||||
.then(() => setRequestState(RequestState.SUCCESS))
|
.then(() => setRequestState(RequestState.SUCCESS))
|
||||||
.catch((errStatus) => setRequestState(RequestState.FAILED));
|
.catch(() => setRequestState(RequestState.FAILED));
|
||||||
}, 500);
|
}, 500);
|
||||||
}, [usingPrimaryCalendar, maxFutureBookingDays, minEarliestBookingTime]);
|
}, [usingPrimaryCalendar, maxFutureBookingDays, minEarliestBookingTime]);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ export const Constants = {
|
||||||
//STATIC_CONTENT_ADDRESS: staticContentAddress,
|
//STATIC_CONTENT_ADDRESS: staticContentAddress,
|
||||||
// WS_ADDRESS: wsAddress,
|
// WS_ADDRESS: wsAddress,
|
||||||
EMBED_CALENDAR_ADDRESS: "https://calendar.ex.umbach.dev/embed/?id=",
|
EMBED_CALENDAR_ADDRESS: "https://calendar.ex.umbach.dev/embed/?id=",
|
||||||
|
EMBED_CALENDAR_SCRIPT_ADDRESS:
|
||||||
|
"https://calendar.ex.umbach.dev/embedPopup/script.js",
|
||||||
ROUTE_PATHS: {
|
ROUTE_PATHS: {
|
||||||
AUTHENTICATION: {
|
AUTHENTICATION: {
|
||||||
LOGIN: "/login",
|
LOGIN: "/login",
|
||||||
|
|
Loading…
Reference in New Issue