import dayjs from 'dayjs' import { HelpCircle } from 'lucide-react' import { useMemo, useState } from 'react' import { Calendar, cn } from 'ui' import { Timezone } from './PITR.types' import { constrainDateToRange, formatNumberToTwoDigits, getClientTimezone, getDatesBetweenRange, } from './PITR.utils' import TimeInput from './TimeInput' import { TimezoneSelection } from './TimezoneSelection' import { ButtonTooltip } from '@/components/ui/ButtonTooltip' import { FormPanel } from '@/components/ui/Forms/FormPanel' import InformationBox from '@/components/ui/InformationBox' type Props = { onSubmit: (data: { recoveryTimeTargetUnix: number recoveryTimeString: string recoveryTimeStringUtc: string }) => void earliestAvailableBackupUnix: number latestAvailableBackupUnix: number disabled?: boolean } export function PITRForm({ onSubmit, earliestAvailableBackupUnix, latestAvailableBackupUnix, disabled = false, }: Props) { const [selectedTimezone, setSelectedTimezone] = useState(getClientTimezone()) const earliestAvailableBackup = dayjs .unix(earliestAvailableBackupUnix ?? 0) .tz(selectedTimezone.utc[0]) const latestAvailableBackup = dayjs .unix(latestAvailableBackupUnix ?? 0) .tz(selectedTimezone.utc[0]) const earliestAvailableBackupAsDate = earliestAvailableBackup.toDate() const latestAvailableBackupAsDate = latestAvailableBackup.toDate() const [selectedDateRaw, setSelectedDateRaw] = useState(latestAvailableBackup.toDate()) const selectedDate = dayjs(selectedDateRaw).tz(selectedTimezone.utc[0], true) const isSelectedOnEarliestDay = selectedDate.isSame(earliestAvailableBackup, 'day') const isSelectedOnLatestDay = selectedDate.isSame(latestAvailableBackup, 'day') const availableDates = getDatesBetweenRange(earliestAvailableBackup, latestAvailableBackup) const selectedTime = { h: selectedDate.hour(), m: selectedDate.minute(), s: selectedDate.second(), } const earliestAvailableBackupTime = { h: earliestAvailableBackup.hour(), m: earliestAvailableBackup.minute(), s: earliestAvailableBackup.second(), } const latestAvailableBackupTime = { h: latestAvailableBackup.hour(), m: latestAvailableBackup.minute(), s: latestAvailableBackup.second(), } const recoveryTimeTargetUnix = selectedDate.unix() const recoveryTimeString = selectedDate.format('DD MMM YYYY HH:mm:ss') const recoveryTimeStringUtc = selectedDate.utc().format('DD MMM YYYY HH:mm:ss') const isWithinRange = useMemo( () => (!!selectedDate && selectedDate.isSame(latestAvailableBackup)) || selectedDate.isSame(earliestAvailableBackup) || (selectedDate.isBefore(latestAvailableBackup) && selectedDate.isAfter(earliestAvailableBackup)), [selectedDate, latestAvailableBackup, earliestAvailableBackup] ) const onUpdateDate = (date: Date) => { setSelectedDateRaw( constrainDateToRange( dayjs(date).tz(selectedTimezone.utc[0], true), earliestAvailableBackup, latestAvailableBackup ).toDate() ) } const handleSubmit = () => { onSubmit({ recoveryTimeTargetUnix, recoveryTimeString, recoveryTimeStringUtc, }) } return (
Continue
} >
{availableDates.length > 1 && (

Point in time back up available

)}
{!selectedDate ? (
} title="Select a date which you'd like to restore your database to" />
) : (

Date to restore to

{dayjs(selectedDate).format('DD MMM YYYY')} , {formatNumberToTwoDigits(selectedTime.h)}: {formatNumberToTwoDigits(selectedTime.m)}: {formatNumberToTwoDigits(selectedTime.s)}

Time zone

Recovery time

{ const newDate = dayjs(selectedDateRaw) .set('hour', h) .set('minute', m) .set('second', s) setSelectedDateRaw(newDate.toDate()) }} />

Enter a time within the available range to restore from.
Backups are captured every 2 minutes, allowing you to enter a time and restore your database to the closest backup point. We'll match the time you enter to the closest backup within the 2-minute window

{isSelectedOnEarliestDay && (

Earliest backup available for this date:{' '} {earliestAvailableBackup.format('HH:mm:ss')}

)} {isSelectedOnLatestDay && (

Latest backup available for this date:{' '} {latestAvailableBackup.format('HH:mm:ss')}

)}
)}
) }