import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import {
Box,
Typography,
TextField,
Button,
FormControlLabel,
Checkbox,
IconButton,
Grid,
Card,
CircularProgress,
Container,
CardContent,
Tabs,
Tab,
RadioGroup,
Radio,
FormControl,
FormLabel
} from '@mui/material';
import { ArrowBack, PlayCircleOutline, Article, Code, Description } from '@mui/icons-material';
import { useGlobalInfoStore } from '../../../context/globalInfo';
import { canCreateBrowserInState, getActiveBrowserId, stopRecording } from '../../../api/recording';
import { createScrapeRobot } from "../../../api/storage";
import { AuthContext } from '../../../context/auth';
import { GenericModal } from '../../ui/GenericModal';
interface TabPanelProps {
children?: React.ReactNode;
index: number;
value: number;
}
function TabPanel(props: TabPanelProps) {
const { children, value, index, ...other } = props;
return (
{value === index && {children}}
);
}
const RobotCreate: React.FC = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const { setBrowserId, setRecordingUrl, notify, setRecordingId, setRerenderRobots } = useGlobalInfoStore();
const [tabValue, setTabValue] = useState(0);
const [url, setUrl] = useState('');
const [scrapeRobotName, setScrapeRobotName] = useState('');
const [needsLogin, setNeedsLogin] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [isWarningModalOpen, setWarningModalOpen] = useState(false);
const [activeBrowserId, setActiveBrowserId] = useState('');
const [outputFormats, setOutputFormats] = useState([]);
const { state } = React.useContext(AuthContext);
const { user } = state;
const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
setTabValue(newValue);
};
const handleStartRecording = async () => {
if (!url.trim()) {
notify('error', 'Please enter a valid URL');
return;
}
setIsLoading(true);
try {
const canCreateRecording = await canCreateBrowserInState("recording");
if (!canCreateRecording) {
const activeBrowser = await getActiveBrowserId();
if (activeBrowser) {
setActiveBrowserId(activeBrowser);
setWarningModalOpen(true);
} else {
notify('warning', t('recordingtable.notifications.browser_limit_warning'));
}
setIsLoading(false);
return;
}
setBrowserId('new-recording');
setRecordingUrl(url);
window.sessionStorage.setItem('browserId', 'new-recording');
window.sessionStorage.setItem('recordingUrl', url);
window.sessionStorage.setItem('initialUrl', url);
window.sessionStorage.setItem('needsLogin', needsLogin.toString());
const sessionId = Date.now().toString();
window.sessionStorage.setItem('recordingSessionId', sessionId);
window.open(`/recording-setup?session=${sessionId}`, '_blank');
window.sessionStorage.setItem('nextTabIsRecording', 'true');
// Reset loading state immediately after opening new tab
setIsLoading(false);
navigate('/robots');
} catch (error) {
console.error('Error starting recording:', error);
notify('error', 'Failed to start recording. Please try again.');
setIsLoading(false);
}
};
const handleDiscardAndCreate = async () => {
if (activeBrowserId) {
await stopRecording(activeBrowserId);
notify('warning', t('browser_recording.notifications.terminated'));
}
setWarningModalOpen(false);
setIsLoading(false);
// Continue with the original Recording logic
setBrowserId('new-recording');
setRecordingUrl(url);
window.sessionStorage.setItem('browserId', 'new-recording');
window.sessionStorage.setItem('recordingUrl', url);
window.sessionStorage.setItem('initialUrl', url);
window.sessionStorage.setItem('needsLogin', needsLogin.toString());
const sessionId = Date.now().toString();
window.sessionStorage.setItem('recordingSessionId', sessionId);
window.open(`/recording-setup?session=${sessionId}`, '_blank');
window.sessionStorage.setItem('nextTabIsRecording', 'true');
navigate('/robots');
};
return (
navigate('/robots')}
sx={{
ml: -1,
mr: 1,
color: theme => theme.palette.text.primary,
backgroundColor: 'transparent !important',
'&:hover': {
backgroundColor: 'transparent !important',
},
'&:active': {
backgroundColor: 'transparent !important',
},
'&:focus': {
backgroundColor: 'transparent !important',
},
'&:focus-visible': {
backgroundColor: 'transparent !important',
},
}}
disableRipple
aria-label="Go back"
>
Create New Robot
{/* Logo (kept as original) */}
Extract structured data from websites in a few clicks.
{/* Origin URL Input */}
setUrl(e.target.value)}
/>
{/* Checkbox */}
setNeedsLogin(e.target.checked)}
color="primary"
/>
}
label="This website needs logging in."
/>
{/* Button */}
: null}
>
{isLoading ? 'Starting...' : 'Start Recording'}
First time creating a robot?
Get help and learn how to use Maxun effectively.
{/* YouTube Tutorials */}
window.open("https://www.youtube.com/@MaxunOSS/videos", "_blank")}
>
theme.palette.mode === 'light' ? 'rgba(0, 0, 0, 0.54)' : '',
}}
>
Video Tutorials
Watch step-by-step guides
{/* Documentation */}
window.open("https://docs.maxun.dev", "_blank")}
>
theme.palette.mode === 'light' ? 'rgba(0, 0, 0, 0.54)' : '',
}}
>
Documentation
Explore detailed guides
Turn websites into LLM-ready Markdown & clean HTML for AI apps.
setScrapeRobotName(e.target.value)}
sx={{ mb: 2 }}
label="Robot Name"
/>
setUrl(e.target.value)}
label="Website URL"
sx={{ mb: 2 }}
/>
Output Format (Select at least one)
{
if (e.target.checked) {
setOutputFormats([...outputFormats, 'markdown']);
} else {
setOutputFormats(outputFormats.filter(f => f !== 'markdown'));
}
}}
/>
}
label="Markdown"
/>
{
if (e.target.checked) {
setOutputFormats([...outputFormats, 'html']);
} else {
setOutputFormats(outputFormats.filter(f => f !== 'html'));
}
}}
/>
}
label="HTML"
/>
{
setWarningModalOpen(false);
setIsLoading(false);
}} modalStyle={modalStyle}>
{t('recordingtable.warning_modal.title')}
{t('recordingtable.warning_modal.message')}
);
};
export default RobotCreate;
const modalStyle = {
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: '30%',
backgroundColor: 'background.paper',
p: 4,
height: 'fit-content',
display: 'block',
padding: '20px',
};