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)",
|
||||
"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": {
|
||||
"pageTitle": "Einstellungen"
|
||||
|
|
|
@ -272,7 +272,19 @@
|
|||
"checkboxDeleteCalendars": "Delete calendar for opening hours and appointments (all appointments are deleted and cannot be restored)",
|
||||
"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": {
|
||||
"pageTitle": "Settings"
|
||||
|
|
|
@ -2,8 +2,10 @@ import {
|
|||
Button,
|
||||
Card,
|
||||
Col,
|
||||
Flex,
|
||||
Form,
|
||||
Grid,
|
||||
QRCode,
|
||||
Result,
|
||||
Row,
|
||||
Space,
|
||||
|
@ -34,8 +36,17 @@ import {
|
|||
} from "../../../Components/MyRequestStateItem";
|
||||
import MyModal, {
|
||||
MyModalCloseConfirmButtonFooter,
|
||||
MyModalOnlyCloseButtonFooter,
|
||||
} from "../../../Components/MyModal";
|
||||
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;
|
||||
|
||||
|
@ -191,20 +202,22 @@ export default function StoreCalendar() {
|
|||
</Col>
|
||||
|
||||
<Col xs={24}>
|
||||
<Card title={t("calendar.calendarFrameCustomerView")}>
|
||||
<CalendarFrame storeId={storeId} />
|
||||
</Card>
|
||||
<CalendarFrameCard storeId={storeId} />
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function CalendarFrame({ storeId }) {
|
||||
function CalendarFrameCard({ storeId }) {
|
||||
const { t } = useTranslation();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card
|
||||
title={t("calendar.calendarFrameCustomerView")}
|
||||
extra={<ModalShareCalendarLink storeId={storeId} />}
|
||||
>
|
||||
{isLoading && (
|
||||
<div
|
||||
style={{
|
||||
|
@ -225,6 +238,139 @@ function CalendarFrame({ storeId }) {
|
|||
height={530}
|
||||
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,
|
||||
})
|
||||
.then(() => setRequestState(RequestState.SUCCESS))
|
||||
.catch((errStatus) => setRequestState(RequestState.FAILED));
|
||||
.catch(() => setRequestState(RequestState.FAILED));
|
||||
}, 500);
|
||||
}, [usingPrimaryCalendar, maxFutureBookingDays, minEarliestBookingTime]);
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ export const Constants = {
|
|||
//STATIC_CONTENT_ADDRESS: staticContentAddress,
|
||||
// WS_ADDRESS: wsAddress,
|
||||
EMBED_CALENDAR_ADDRESS: "https://calendar.ex.umbach.dev/embed/?id=",
|
||||
EMBED_CALENDAR_SCRIPT_ADDRESS:
|
||||
"https://calendar.ex.umbach.dev/embedPopup/script.js",
|
||||
ROUTE_PATHS: {
|
||||
AUTHENTICATION: {
|
||||
LOGIN: "/login",
|
||||
|
|
Loading…
Reference in New Issue