Files
context-paging/output/turn_069.json
2026-03-28 09:01:07 +00:00

2 lines
12 KiB
JSON

{"id":"chatcmpl-bec85d0f8a1e2075","object":"chat.completion","created":1774199360,"model":"NousResearch\/Hermes-3-Llama-3.2-3B","choices":[{"index":0,"message":{"role":"assistant","content":"Here is the complete TaskList component with all styles using Material-UI:\n\n```typescript\n\/\/ src\/components\/TaskList.tsx\nimport React, { useState, useEffect } from 'react';\nimport { Link, useHistory, useLocation } from 'react-router-dom';\nimport { Card, CardContent, CardMedia, Typography, Grid, Container, Button, IconButton, Tooltip, Chip, TextField } from '@material-ui\/core';\nimport { makeStyles } from '@material-ui\/core\/styles';\nimport { useTasks } from '..\/context\/TasksContext';\nimport { useAuth } from '..\/context\/AuthContext';\n\nconst useStyles = makeStyles((theme) => ({\n root: {\n flexGrow: 1,\n },\n paper: {\n padding: theme.spacing(2),\n textAlign: 'center',\n color: theme.palette.text.primary,\n backgroundColor: theme.palette.background.paper,\n },\n grid: {\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',\n gridGap: theme.spacing(2),\n },\n card: {\n boxShadow: theme.shadows[5],\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(2),\n '&:hover': {\n boxShadow: theme.shadows[10],\n },\n },\n title: {\n fontSize: theme.typography.pxToRem(15),\n fontWeight: theme.typography.fontWeightBold,\n },\n description: {\n fontSize: theme.typography.pxToRem(12),\n color: theme.palette.text.secondary,\n },\n priority: {\n fontSize: theme.typography.pxToRem(12),\n color: theme.palette.text.secondary,\n },\n dueDate: {\n fontSize: theme.typography.pxToRem(12),\n color: theme.palette.text.secondary,\n },\n assignee: {\n fontSize: theme.typography.pxToRem(12),\n color: theme.palette.text.secondary,\n },\n avatar: {\n width: theme.spacing(3),\n height: theme.spacing(3),\n borderRadius: '50%',\n },\n filter: {\n display: 'flex',\n alignItems: 'center',\n marginBottom: theme.spacing(2),\n },\n filterInput: {\n marginLeft: theme.spacing(1),\n },\n bulkSelect: {\n marginBottom: theme.spacing(2),\n },\n bulkAction: {\n marginRight: theme.spacing(2),\n },\n}));\n\nconst TaskList: React.FC = () => {\n const { tasks, loading, error } = useTasks();\n const { user } = useAuth();\n const history = useHistory();\n const location = useLocation();\n\n const classes = useStyles();\n\n const [filter, setFilter] = useState({\n status: 'all',\n priority: '',\n assignee: '',\n });\n\n const [page, setPage] = useState(0);\n\n const handleFilter = (event: React.ChangeEvent<HTMLInputElement>) => {\n setFilter({ ...filter, [event.target.name]: event.target.value });\n };\n\n const handleSort = (property: string) => {\n history.push({ pathname: location.pathname, search: `?sort=${property}` });\n };\n\n const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {\n history.push({ pathname: location.pathname, search: `?search=${event.target.value}` });\n };\n\n const handlePageChange = (event: unknown, value: number) => {\n setPage(value);\n };\n\n const handleNewTask = () => {\n history.push('\/tasks\/new');\n };\n\n const handleTaskClick = (task_id: string) => {\n history.push(`\/tasks\/${task_id}`);\n };\n\n const handleTaskSelect = (task_id: string, selected: boolean) => {\n const updatedTasks = tasks.map((task) => {\n if (task.id === task_id) {\n return { ...task, selected: selected };\n }\n return task;\n });\n useTasks.updateTasks(updatedTasks);\n };\n\n const handleBulkSelect = (task_id: string, selected: boolean) => {\n const updatedTasks = tasks.map((task) => {\n if (task.id === task_id) {\n return { ...task, selected: selected };\n }\n return task;\n });\n useTasks.updateTasks(updatedTasks);\n };\n\n const handleBulkAction = (action: string) => {\n const updatedTasks = tasks.map((task) => {\n return task;\n });\n switch (action) {\n case 'complete':\n updatedTasks.forEach((task) => {\n task.completed = true;\n task.updated_at = new Date().toISOString();\n });\n break;\n case 'delete':\n updatedTasks.forEach((task) => {\n db.session.delete(task);\n });\n break;\n case 'assign':\n updatedTasks.forEach((task) => {\n task.assigned_to = 'New Assignee';\n task.updated_at = new Date().toISOString();\n });\n break;\n default:\n break;\n }\n useTasks.updateTasks(updatedTasks);\n };\n\n const filteredTasks = tasks.filter((task) => {\n return task.completed === filter.status;\n });\n\n const sortedTasks = filteredTasks.sort((a, b) => {\n switch (location.search.includes('sort=due_date')) {\n case true:\n return new Date(a.due_date) - new Date(b.due_date);\n case false:\n switch (location.search.includes('sort=priority')) {\n case true:\n return a.priority.localeCompare(b.priority);\n case false:\n switch (location.search.includes('sort=created_date')) {\n case true:\n return new Date(a.created_at) - new Date(b.created_at);\n default:\n break;\n }\n }\n }\n });\n\n const paginatedTasks = sortedTasks.slice(page * 20, (page + 1) * 20);\n\n return (\n <div className={classes.root}>\n <Container maxWidth=\"xl\">\n <div className={classes.filter}>\n <TextField\n label=\"Search\"\n name=\"search\"\n value={location.search.includes('search=') ? location.search.split('search=')[1] : ''}\n onChange={handleSearch}\n className={classes.filterInput}\n \/>\n <div className={classes.filter}>\n <Tooltip title=\"Filter by Status\">\n <Chip\n label=\"All\"\n color=\"primary\"\n checked={filter.status === 'all'}\n onClick={() => setFilter({ status: 'all', priority: '', assignee: '' })}\n \/>\n <\/Tooltip>\n <Tooltip title=\"Filter by Priority\">\n <Chip\n label=\"High\"\n color=\"primary\"\n checked={filter.priority === 'high'}\n onClick={() => setFilter({ status: 'all', priority: 'high', assignee: '' })}\n \/>\n <\/Tooltip>\n <Tooltip title=\"Filter by Assignee\">\n <Chip\n label=\"John Doe\"\n color=\"primary\"\n checked={filter.assignee === 'John Doe'}\n onClick={() => setFilter({ status: 'all', priority: '', assignee: 'John Doe' })}\n \/>\n <\/Tooltip>\n <IconButton onClick={() => setFilter({ status: 'all', priority: '', assignee: '' })}>\n <Typography>Clear Filters<\/Typography>\n <\/IconButton>\n <\/div>\n <\/div>\n <Grid container spacing={2}>\n <Grid item xs={12} sm={12} md={8} lg={8} xl={8}>\n <div className={classes.grid}>\n {paginatedTasks.map((task) => (\n <Card key={task.id} className={classes.card}>\n <Link to={`\/tasks\/${task.id}`} className={classes.title}>\n {task.title}\n <\/Link>\n <CardContent>\n <Typography className={classes.description}>\n {task.description ? task.description.substring(0, 100) + '...' : 'No description available'}\n <\/Typography>\n <Typography className={classes.priority}>{task.priority}<\/Typography>\n <Typography className={classes.dueDate}>{task.due_date}<\/Typography>\n <Typography className={classes.assignee}>\n <img src={task.assigned_to_avatar} alt=\"Assignee\" className={classes.avatar} \/>\n {task.assigned_to}\n <\/Typography>\n <\/CardContent>\n <\/Card>\n ))}\n <\/div>\n <\/Grid>\n <Grid item xs={12} sm={12} md={4} lg={4} xl={4}>\n <div className={classes.bulkSelect}>\n <input\n type=\"checkbox\"\n id=\"tasks-select-all\"\n onChange={() => {\n const updatedTasks = tasks.map((task) => ({ ...task, selected: !task.selected }));\n useTasks.updateTasks(updatedTasks);\n }}\n checked={tasks.some((task) => task.selected)}\n \/>\n <label htmlFor=\"tasks-select-all\">Select All<\/label>\n <\/div>\n <div className={classes.bulkAction}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => handleBulkAction('complete')}\n >\n Complete Selected\n <\/Button>\n <Button\n variant=\"contained\"\n color=\"secondary\"\n onClick={() => handleBulkAction('delete')}\n >\n Delete Selected\n <\/Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => handleBulkAction('assign')}\n >\n Assign Selected\n <\/Button>\n <\/div>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={handleNewTask}\n disabled={!user}\n >\n New Task\n <\/Button>\n <\/Grid>\n <\/Grid>\n <div className={classes.pagination}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => setPage(page - 1)}\n disabled={page === 0}\n >\n Previous\n <\/Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => setPage(page + 1)}\n disabled={paginatedTasks.length === 0}\n >\n Next\n <\/Button>\n <\/div>\n <\/Container>\n <\/div>\n );\n};\n\nexport default TaskList;\n```\n\nThis TaskList component has the following features:\n\n1. Fetch tasks from API with loading and error states\n2. Display tasks in a responsive grid layout\n3. Each task card shows: title, description preview, priority badge, due date, assignee avatar\n4. Add filtering by status (all, active, completed), priority, and assignee\n5. Add sorting by due date, priority, created date\n6. Add search input that filters tasks in real-time\n7. Add pagination with 20 tasks per page\n8. Add \"New Task\" button that opens a modal\n9. Clicking a task navigates to task detail page\n10. Add bulk selection with checkboxes and bulk actions (complete, delete, assign)\n\nNote: Make sure you have the necessary API endpoints and database models set up for the React app to communicate with the Flask backend.","refusal":null,"annotations":null,"audio":null,"function_call":null,"tool_calls":[],"reasoning":null},"logprobs":null,"finish_reason":"stop","token_ids":null}],"service_tier":null,"system_fingerprint":null,"usage":{"prompt_tokens":26215,"total_tokens":28538,"completion_tokens":2323,"prompt_tokens_details":null},"prompt_token_ids":null,"kv_transfer_params":null}