116 lines
2.8 KiB
TypeScript
116 lines
2.8 KiB
TypeScript
|
import { useState } from 'react';
|
||
|
import {
|
||
|
Dialog,
|
||
|
DialogTitle,
|
||
|
DialogContent,
|
||
|
DialogActions,
|
||
|
Button,
|
||
|
TextField,
|
||
|
Box,
|
||
|
} from '@mui/material';
|
||
|
|
||
|
interface BaseCreateData {
|
||
|
name: string;
|
||
|
}
|
||
|
|
||
|
interface CreateTaskData extends BaseCreateData {
|
||
|
groupId: string;
|
||
|
}
|
||
|
|
||
|
interface CreateStepData extends BaseCreateData {
|
||
|
instructions: string;
|
||
|
taskId: string;
|
||
|
order: number;
|
||
|
}
|
||
|
|
||
|
type CreateData = BaseCreateData | CreateTaskData | CreateStepData;
|
||
|
|
||
|
interface CreateDialogProps {
|
||
|
open: boolean;
|
||
|
onClose: () => void;
|
||
|
onSubmit: (data: CreateData) => void;
|
||
|
title: string;
|
||
|
type: 'group' | 'task' | 'step';
|
||
|
parentId?: string;
|
||
|
}
|
||
|
|
||
|
export function CreateDialog({ open, onClose, onSubmit, title, type, parentId }: CreateDialogProps) {
|
||
|
const [name, setName] = useState('');
|
||
|
const [instructions, setInstructions] = useState('');
|
||
|
const [order, setOrder] = useState(1);
|
||
|
|
||
|
const handleSubmit = () => {
|
||
|
if (type === 'task' && !parentId) {
|
||
|
console.error('Cannot create task: no group selected');
|
||
|
return;
|
||
|
}
|
||
|
if (type === 'step' && !parentId) {
|
||
|
console.error('Cannot create step: no task selected');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const data: CreateData = {
|
||
|
name,
|
||
|
...(type === 'task' && { groupId: parentId }),
|
||
|
...(type === 'step' && {
|
||
|
instructions,
|
||
|
taskId: parentId,
|
||
|
order,
|
||
|
}),
|
||
|
};
|
||
|
onSubmit(data);
|
||
|
handleClose();
|
||
|
};
|
||
|
|
||
|
const handleClose = () => {
|
||
|
setName('');
|
||
|
setInstructions('');
|
||
|
setOrder(1);
|
||
|
onClose();
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
|
||
|
<DialogTitle>{title}</DialogTitle>
|
||
|
<DialogContent>
|
||
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, pt: 1 }}>
|
||
|
<TextField
|
||
|
label="Name"
|
||
|
value={name}
|
||
|
onChange={(e) => setName(e.target.value)}
|
||
|
fullWidth
|
||
|
required
|
||
|
/>
|
||
|
{type === 'step' && (
|
||
|
<>
|
||
|
<TextField
|
||
|
label="Instructions"
|
||
|
value={instructions}
|
||
|
onChange={(e) => setInstructions(e.target.value)}
|
||
|
fullWidth
|
||
|
required
|
||
|
multiline
|
||
|
rows={4}
|
||
|
/>
|
||
|
<TextField
|
||
|
label="Order"
|
||
|
type="number"
|
||
|
value={order}
|
||
|
onChange={(e) => setOrder(parseInt(e.target.value))}
|
||
|
fullWidth
|
||
|
required
|
||
|
inputProps={{ min: 1 }}
|
||
|
/>
|
||
|
</>
|
||
|
)}
|
||
|
</Box>
|
||
|
</DialogContent>
|
||
|
<DialogActions>
|
||
|
<Button onClick={handleClose}>Cancel</Button>
|
||
|
<Button onClick={handleSubmit} variant="contained" disabled={!name || (type === 'step' && !instructions)}>
|
||
|
Create
|
||
|
</Button>
|
||
|
</DialogActions>
|
||
|
</Dialog>
|
||
|
);
|
||
|
}
|