App.tsx
import React, { useState } from 'react';
import { Form } from './Form';
import { List } from './List';
import { Container, Typography } from '@mui/material';
export type ListItem = {
id: number;
title: string;
details: string;
};
const App: React.FC = () => {
const [listItems, setListItems] = useState<ListItem[]>([]);
const addItem = (title: string, details: string) => {
const newItem: ListItem = {
id: listItems.length ? listItems[listItems.length - 1].id + 1 : 1,
title,
details,
};
setListItems([...listItems, newItem]);
};
const removeItem = (id: number) => {
setListItems(listItems.filter(item => item.id !== id));
};
return (
<Container>
<Typography variant="h4" gutterBottom>My List App</Typography>
<Form addItem={addItem} />
<List items={listItems} removeItem={removeItem} />
</Container>
);
};
export default App;
Form.tsx
import React, { useState } from 'react';
import { TextField, Button, Box, Alert } from '@mui/material';
type FormProps = {
addItem: (title: string, details: string) => void;
};
export const Form: React.FC<FormProps> = ({ addItem }) => {
const [title, setTitle] = useState('');
const [details, setDetails] = useState('');
const [showAlert, setShowAlert] = useState(false);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (title) {
addItem(title, details);
setTitle('');
setDetails('');
setShowAlert(false);
} else {
setShowAlert(true);
}
};
return (
<Box component="form" onSubmit={handleSubmit} sx={{ mb: 2 }}>
{showAlert && (
<Alert severity="warning" onClose={() => setShowAlert(false)}>
Title is required!
</Alert>
)}
<TextField
label="Title"
value={title}
onChange={(e) => setTitle(e.target.value)}
fullWidth
margin="normal"
/>
<TextField
label="Details"
value={details}
onChange={(e) => setDetails(e.target.value)}
fullWidth
margin="normal"
/>
<Button type="submit" variant="contained" color="primary" sx={{ mt: 2 }}>
Add Item
</Button>
</Box>
);
};
List.tsx
import React from 'react';
import { ListItem as ListItemType } from './App';
import { List as MUIList, ListItem, ListItemText, IconButton, Divider } from '@mui/material';
import DeleteIcon from '@mui/icons-material/Delete';
type ListProps = {
items: ListItemType[];
removeItem: (id: number) => void;
};
export const List: React.FC<ListProps> = ({ items, removeItem }) => {
return (
<MUIList>
{items.map((item) => (
<React.Fragment key={item.id}>
<ListItem
secondaryAction={
<IconButton edge="end" aria-label="delete" onClick={() => removeItem(item.id)}>
<DeleteIcon />
</IconButton>
}
>
<ListItemText primary={item.title} secondary={item.details} />
</ListItem>
<Divider />
</React.Fragment>
))}
</MUIList>
);
};