import DailyIframe from "@daily-co/daily-js"; import MarkdownIt from "markdown-it"; import type { GetServerSidePropsContext } from "next"; import Head from "next/head"; import { useState, useEffect } from "react"; import dayjs from "@calcom/dayjs"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import classNames from "@calcom/lib/classNames"; import { APP_NAME, SEO_IMG_OGIMG_VIDEO, WEBSITE_URL } from "@calcom/lib/constants"; import { formatToLocalizedDate, formatToLocalizedTime } from "@calcom/lib/date-fns"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import prisma, { bookingMinimalSelect } from "@calcom/prisma"; import type { inferSSRProps } from "@calcom/types/inferSSRProps"; import { FiChevronRight } from "@calcom/ui/components/icon"; import { ssrInit } from "@server/lib/ssr"; export type JoinCallPageProps = inferSSRProps; const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true }); export default function JoinCall(props: JoinCallPageProps) { const { t } = useLocale(); const { meetingUrl, meetingPassword, booking } = props; useEffect(() => { const callFrame = DailyIframe.createFrame({ theme: { colors: { accent: "#FFF", accentText: "#111111", background: "#111111", backgroundAccent: "#111111", baseText: "#FFF", border: "#292929", mainAreaBg: "#111111", mainAreaBgAccent: "#111111", mainAreaText: "#FFF", supportiveText: "#FFF", }, }, showLeaveButton: true, iframeStyle: { position: "fixed", width: "100%", height: "100%", }, url: meetingUrl, ...(typeof meetingPassword === "string" && { token: meetingPassword }), }); callFrame.join(); return () => { callFrame.destroy(); }; }, []); const title = `${APP_NAME} Video`; return ( <> {title}
Cal.com Logo
); } interface ProgressBarProps { startTime: string; endTime: string; } function ProgressBar(props: ProgressBarProps) { const { startTime, endTime } = props; const currentTime = dayjs().second(0).millisecond(0); const startingTime = dayjs(startTime).second(0).millisecond(0); const isPast = currentTime.isAfter(startingTime); const currentDifference = dayjs().diff(startingTime, "minutes"); const startDuration = dayjs(endTime).diff(startingTime, "minutes"); const [duration] = useState(() => { if (currentDifference >= 0 && isPast) { return startDuration - currentDifference; } else { return startDuration; } }); const prev = startDuration - duration; const percentage = prev * (100 / startDuration); return (

{duration} minutes

); } interface VideoMeetingInfo { booking: JoinCallPageProps["booking"]; } export function VideoMeetingInfo(props: VideoMeetingInfo) { const [open, setOpen] = useState(false); const { booking } = props; const endTime = new Date(booking.endTime); const startTime = new Date(booking.startTime); return ( <> ); } export async function getServerSideProps(context: GetServerSidePropsContext) { const { req, res } = context; const ssr = await ssrInit(context); const booking = await prisma.booking.findUnique({ where: { uid: context.query.uid as string, }, select: { ...bookingMinimalSelect, uid: true, description: true, user: { select: { id: true, credentials: true, timeZone: true, name: true, email: true, }, }, references: { select: { uid: true, type: true, meetingUrl: true, meetingPassword: true, }, where: { type: "daily_video", }, }, }, }); if (!booking || booking.references.length === 0 || !booking.references[0].meetingUrl) { return { redirect: { destination: "/video/no-meeting-found", permanent: false, }, }; } //daily.co calls have a 60 minute exit buffer when a user enters a call when it's not available it will trigger the modals const now = new Date(); const exitDate = new Date(now.getTime() - 60 * 60 * 1000); //find out if the meeting is in the past const isPast = booking?.endTime <= exitDate; if (isPast) { return { redirect: { destination: `/video/meeting-ended/${booking?.uid}`, permanent: false, }, }; } const bookingObj = Object.assign({}, booking, { startTime: booking.startTime.toString(), endTime: booking.endTime.toString(), }); const session = await getServerSession({ req, res }); // set meetingPassword to null for guests if (session?.user.id !== bookingObj.user?.id) { bookingObj.references.forEach((bookRef) => { bookRef.meetingPassword = null; }); } return { props: { meetingUrl: bookingObj.references[0].meetingUrl ?? "", ...(typeof bookingObj.references[0].meetingPassword === "string" && { meetingPassword: bookingObj.references[0].meetingPassword, }), booking: bookingObj, trpcState: ssr.dehydrate(), }, }; }