import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useState } from "react"; import { useNavigate } from "react-router"; import { useApi } from "../api/context"; import { errorMessage } from "../state/actions"; import { PLAYER_STATE_KEY } from "../state/player"; import { Button, Sheet } from "../ui"; const BACKUP_KEY = ["backup-code"] as const; /** "Back up company": make a code (shown once), or replace the existing one (decision 0.5.72). */ export function BackupCompany() { const api = useApi(); const queryClient = useQueryClient(); const [open, setOpen] = useState(false); const [copied, setCopied] = useState(false); const status = useQuery({ queryKey: BACKUP_KEY, queryFn: () => api.call("getBackupCode", {}), enabled: open, }); const create = useMutation({ mutationFn: () => api.call("createBackupCode", {}), onSuccess: () => void queryClient.invalidateQueries({ queryKey: BACKUP_KEY }), }); const code = create.data?.code; const close = () => { setOpen(false); setCopied(false); create.reset(); }; const copy = (text: string) => { void navigator.clipboard ?.writeText(text) .then(() => setCopied(true)) .catch(() => setCopied(false)); }; let body; if (code) { body = ( <>

{code}

Keep this somewhere safe. Anyone with this code can open your company.

); } else if (status.isPending) { body =

Checking…

; } else if (status.data?.hasCode) { body = ( <>

You already have a backup code. It is only shown when it is made, so if you lost it, make a new one.

Your old code will stop working as soon as you generate a new one.

); } else { body = ( <>

A backup code lets you open this company on any device, or get it back if this one is lost. No email or password.

); } return ( <> {open && ( {body} {(create.isError || status.isError) && (

{errorMessage(create.error ?? status.error)}

)}
)} ); } /** * "Restore a company": enter a backup code to open that company on this * device. `pastTutorial` warns that this device's own company is left behind. */ export function RestoreCompany({ pastTutorial }: { pastTutorial: boolean }) { const api = useApi(); const queryClient = useQueryClient(); const navigate = useNavigate(); const [open, setOpen] = useState(false); const [code, setCode] = useState(""); const restore = useMutation({ mutationFn: () => api.call("restoreCompany", { code }), onSuccess: async ({ state }) => { queryClient.setQueryData(PLAYER_STATE_KEY, state); await queryClient.invalidateQueries({ queryKey: ["board"] }); setOpen(false); void navigate("/"); }, }); return ( <> {open && ( {pastTutorial && (

This device's current company will be left behind. Back it up first if you want to keep it.

)}
{ e.preventDefault(); if (code.trim()) restore.mutate(); }} > {restore.isError && (

{errorMessage(restore.error)}

)}
)} ); }