Simple frontend added, tests are required
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
import React from 'react'
|
||||
import { ThemeProvider, createTheme, CssBaseline } from '@mui/material'
|
||||
import { Box, Grid, Button, Alert, CircularProgress } from '@mui/material'
|
||||
import { PlayArrow } from '@mui/icons-material'
|
||||
import { Layout } from './components/Layout'
|
||||
import { UploadZone } from './components/UploadZone'
|
||||
import { TracklistEditor } from './components/TracklistEditor'
|
||||
import { OptionsPanel } from './components/OptionsPanel'
|
||||
import { ProgressDisplay } from './components/ProgressDisplay'
|
||||
import { DownloadSection } from './components/DownloadSection'
|
||||
import { useUploadStore } from './stores/uploadStore'
|
||||
import { useTracklistStore } from './stores/tracklistStore'
|
||||
import { useOptionsStore } from './stores/optionsStore'
|
||||
import { useTaskStore } from './stores/taskStore'
|
||||
import { useUIStore } from './stores/uiStore'
|
||||
import { useWebSocket } from './hooks/useWebSocket'
|
||||
import { startSplit } from './api/client'
|
||||
|
||||
const App: React.FC = () => {
|
||||
const { theme } = useUIStore()
|
||||
const { taskId, file } = useUploadStore()
|
||||
const { entries, isValid } = useTracklistStore()
|
||||
const { options } = useOptionsStore()
|
||||
const { isProcessing, status, setStatus, setProgress, setMessage, setError, setIsProcessing, addLog, reset } =
|
||||
useTaskStore()
|
||||
|
||||
// Connect WebSocket when taskId is available and processing
|
||||
useWebSocket(taskId && isProcessing ? taskId : null)
|
||||
|
||||
const handleSplit = async () => {
|
||||
if (!taskId) {
|
||||
alert('Please upload a file first')
|
||||
return
|
||||
}
|
||||
|
||||
if (!isValid) {
|
||||
alert('Tracklist has errors. Please fix them before splitting.')
|
||||
return
|
||||
}
|
||||
|
||||
if (entries.length === 0) {
|
||||
alert('Tracklist is empty')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
setIsProcessing(true)
|
||||
addLog('🚀 Starting split...')
|
||||
|
||||
const response = await startSplit(taskId, entries, options)
|
||||
addLog(`✅ Split task started (ID: ${response.task_id})`)
|
||||
} catch (error: any) {
|
||||
setError(error.response?.data?.detail || error.message || 'Failed to start split')
|
||||
addLog(`❌ Error: ${error.response?.data?.detail || error.message || 'Failed to start split'}`)
|
||||
setIsProcessing(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
reset()
|
||||
}
|
||||
|
||||
const isSplitDisabled = !taskId || !isValid || entries.length === 0 || isProcessing
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
theme={createTheme({
|
||||
palette: {
|
||||
mode: theme,
|
||||
},
|
||||
})}
|
||||
>
|
||||
<CssBaseline />
|
||||
<Layout>
|
||||
<Grid container spacing={3}>
|
||||
{/* Upload Section */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<UploadZone />
|
||||
</Grid>
|
||||
|
||||
{/* Tracklist Editor */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<TracklistEditor />
|
||||
</Grid>
|
||||
|
||||
{/* Options Panel */}
|
||||
<Grid item xs={12} md={4}>
|
||||
<OptionsPanel />
|
||||
</Grid>
|
||||
|
||||
{/* Progress / Split Controls */}
|
||||
<Grid item xs={12} md={8}>
|
||||
<Box sx={{ display: 'flex', gap: 2, mb: 3 }}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="success"
|
||||
startIcon={isProcessing ? <CircularProgress size={20} color="inherit" /> : <PlayArrow />}
|
||||
onClick={handleSplit}
|
||||
disabled={isSplitDisabled}
|
||||
sx={{ flex: 1 }}
|
||||
>
|
||||
{isProcessing ? 'Processing...' : 'Split'}
|
||||
</Button>
|
||||
<Button variant="outlined" color="secondary" onClick={handleReset} disabled={isProcessing}>
|
||||
Reset
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
{status && <ProgressDisplay />}
|
||||
{status === 'done' && <DownloadSection />}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Layout>
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
Reference in New Issue
Block a user