Add multiselect.
This commit is contained in:
parent
843d2a8c7b
commit
b09a072fb9
7 changed files with 235 additions and 21 deletions
25
frontend/app/routes/$.tsx
Normal file
25
frontend/app/routes/$.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { redirect } from 'react-router'
|
||||
import type { Route } from './+types/$'
|
||||
|
||||
export async function loader({ request }: Route.LoaderArgs) {
|
||||
const url = new URL(request.url)
|
||||
|
||||
// Handle React DevTools and other development files
|
||||
if (
|
||||
url.pathname.endsWith('.js.map') ||
|
||||
url.pathname.includes('installHook') ||
|
||||
url.pathname.startsWith('/__') ||
|
||||
url.pathname.startsWith('/node_modules/')
|
||||
) {
|
||||
// Return a 404 response for these dev-only requests
|
||||
throw new Response('Not Found', { status: 404 })
|
||||
}
|
||||
|
||||
// For any other unmatched routes, redirect to home
|
||||
return redirect('/')
|
||||
}
|
||||
|
||||
export default function CatchAll() {
|
||||
// This component should never render since we always redirect or throw
|
||||
return null
|
||||
}
|
||||
|
|
@ -4,12 +4,12 @@ import Home from './home'
|
|||
|
||||
describe('Home component', () => {
|
||||
it('should render task management interface', () => {
|
||||
render(<Home />)
|
||||
expect(screen.getByText(/Tasks/i)).toBeInTheDocument()
|
||||
const mockLoaderData = { tasks: [] }
|
||||
render(<Home loaderData={mockLoaderData} />)
|
||||
expect(
|
||||
screen.getByText(/GTD-inspired task management system/i)
|
||||
screen.getByRole('heading', { level: 1, name: /Tasks/i })
|
||||
).toBeInTheDocument()
|
||||
// TaskList component should be rendered (initially shows loading state)
|
||||
expect(screen.getByText(/Loading.../i)).toBeInTheDocument()
|
||||
// TaskList component should be rendered with empty state
|
||||
expect(screen.getByText(/No tasks found/i)).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,27 +1,46 @@
|
|||
import type { Route } from './+types/home'
|
||||
import { Box, Typography, Container } from '@mui/material'
|
||||
import { TaskList } from '~/components/TaskList'
|
||||
import type { Task } from '~/types/task'
|
||||
|
||||
export function meta(_: Route.MetaArgs) {
|
||||
return [
|
||||
{ title: "Captain's Log - Tasks" },
|
||||
{ name: 'description', content: 'GTD-inspired task management system' },
|
||||
{ name: 'description', content: 'Task Dashboard' },
|
||||
]
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
export async function loader(): Promise<{ tasks: Task[] }> {
|
||||
try {
|
||||
// Fetch tasks from the backend API during SSR
|
||||
const apiUrl = process.env.API_URL || 'http://localhost:3000'
|
||||
const response = await fetch(`${apiUrl}/api/tasks`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
console.error('Failed to fetch tasks:', response.statusText)
|
||||
return { tasks: [] }
|
||||
}
|
||||
|
||||
const tasks = await response.json()
|
||||
return { tasks }
|
||||
} catch (error) {
|
||||
console.error('Error fetching tasks during SSR:', error)
|
||||
return { tasks: [] }
|
||||
}
|
||||
}
|
||||
|
||||
export default function Home({ loaderData }: Route.ComponentProps) {
|
||||
return (
|
||||
<Container maxWidth="lg">
|
||||
<Box sx={{ py: 4 }}>
|
||||
<Typography variant="h1" component="h1" gutterBottom>
|
||||
Tasks
|
||||
</Typography>
|
||||
<Typography variant="body1" color="text.secondary" sx={{ mb: 4 }}>
|
||||
Your GTD-inspired task management system. Capture everything, see only
|
||||
what matters.
|
||||
</Typography>
|
||||
|
||||
<TaskList />
|
||||
<TaskList initialTasks={loaderData.tasks} />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue