import type { BlitzPage, ErrorFallbackProps, WithRouterProps } from "blitz"; import { ErrorBoundary, Routes, useRouter, withRouter } from "blitz"; import { useCallback, useEffect } from "react"; import type { TwilioError } from "@twilio/voice-sdk"; import { atom, useAtom } from "jotai"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faPhoneAlt as faPhone } from "@fortawesome/pro-solid-svg-icons"; import useRequireOnboarding from "../../../core/hooks/use-require-onboarding"; import useMakeCall from "../../hooks/use-make-call"; import useDevice from "../../hooks/use-device"; import Keypad from "../../components/keypad"; const OutgoingCall: BlitzPage = () => { useRequireOnboarding(); const [phoneNumber, setPhoneNumber] = useAtom(phoneNumberAtom); const router = useRouter(); const recipient = decodeURIComponent(router.params.recipient); const onHangUp = useCallback(() => setPhoneNumber(""), [setPhoneNumber]); const call = useMakeCall({ recipient, onHangUp }); const { isDeviceReady } = useDevice(); const pressDigit = useAtom(pressDigitAtom)[1]; const onDigitPressProps = useCallback( (digit: string) => ({ onPress() { pressDigit(digit); call.sendDigits(digit); }, }), [call, pressDigit], ); useEffect(() => { if (isDeviceReady) { call.makeCall(); } }, [call, isDeviceReady]); return (
{recipient}
{phoneNumber}
{translateState(call.state)}
); function translateState(state: typeof call.state): string { switch (state) { case "initial": case "ready": return "Connecting..."; case "calling": return "Calling..."; case "call_in_progress": return "In call"; // TODO display time elapsed case "call_ending": return "Call ending..."; case "call_ended": return "Call ended"; } } }; const phoneNumberAtom = atom(""); const pressDigitAtom = atom(null, (get, set, digit: string) => { if (get(phoneNumberAtom).length > 17) { return; } set(phoneNumberAtom, (prevState) => prevState + digit); }); OutgoingCall.authenticate = { redirectTo: Routes.SignIn() }; OutgoingCall.getLayout = (page) => {page}; const ErrorFallback = withRouter(function WrappedErrorFallback({ error, router, }: ErrorFallbackProps & WithRouterProps) { console.log("error", JSON.parse(JSON.stringify(error))); return (

Sorry, an error has occurred during your call

{isTwilioError(error) ? (
						
{error.description} ({error.code})
{error.explanation}
) : null}

We have been automatically notified and we're doing our best to make sure this does not happen again!

); }); function isTwilioError(error: any): error is typeof TwilioError { return error.hasOwnProperty("explanation"); } export default OutgoingCall;