4 changed files with 244 additions and 23 deletions
@ -0,0 +1,216 @@ |
|||||
|
import React, {useState } from 'react'; |
||||
|
import { Box, Button, Card, CardActions, CardContent, Dialog, DialogActions, DialogContent, DialogTitle, Tab, Tabs, TextField, Typography } from '@mui/material'; |
||||
|
import { DatePicker } from '@mui/x-date-pickers'; |
||||
|
import DeleteOutlineRoundedIcon from '@mui/icons-material/DeleteOutlineRounded'; |
||||
|
import EditRoundedIcon from '@mui/icons-material/EditRounded'; |
||||
|
import CakeRoundedIcon from '@mui/icons-material/CakeRounded'; |
||||
|
import EventRoundedIcon from '@mui/icons-material/EventRounded'; |
||||
|
import { useLocalStorage } from '../hooks/useLocalStorage'; |
||||
|
|
||||
|
type Dino = { |
||||
|
name: string, |
||||
|
snames: string, |
||||
|
surname: string, |
||||
|
id: string, |
||||
|
birthday?: string, |
||||
|
description: string, |
||||
|
last?: string |
||||
|
} |
||||
|
|
||||
|
interface TabPanelProps { |
||||
|
children?: React.ReactNode; |
||||
|
id: string; |
||||
|
selected: string; |
||||
|
} |
||||
|
|
||||
|
function TabPanel(props: TabPanelProps) { |
||||
|
const { children, selected, id } = props; |
||||
|
|
||||
|
return ( |
||||
|
<div |
||||
|
role="tabpanel" |
||||
|
hidden={selected !== id} |
||||
|
id={`vertical-tabpanel-${id}`} |
||||
|
aria-labelledby={`vertical-tab-${id}`} |
||||
|
style={{height: "100%"}} |
||||
|
> |
||||
|
{selected === id && |
||||
|
children |
||||
|
} |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
function ShowDino({dino}: {dino: Dino}){ |
||||
|
return( |
||||
|
<CardContent> |
||||
|
<Box sx={{display: "flex", flexDirection: "column", lineHeight: "2"}}> |
||||
|
<Typography variant='h3'>{dino.name} {dino.snames && dino.snames} {dino.surname}</Typography> |
||||
|
{dino.description && <span>{dino.description}</span>} |
||||
|
{dino.birthday && <span><CakeRoundedIcon fontSize="small"/> {(new Date(dino.birthday)).toLocaleDateString()}</span>} |
||||
|
{dino.last && <span><EventRoundedIcon fontSize="small"/> {(new Date(dino.last)).toLocaleDateString()}</span>} |
||||
|
</Box> |
||||
|
</CardContent> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
function ChangeDino({dino, setDino, handleCancel}: {dino: Dino, setDino: (dino: Dino) => void, handleCancel: () => void}){ |
||||
|
|
||||
|
const [name, setName] = React.useState<string>(dino.name) |
||||
|
const [snames, setSnames] = React.useState<string>(dino.snames) |
||||
|
const [surname, setSurname] = React.useState<string>(dino.surname) |
||||
|
const [description, setDescription] = React.useState<string>(dino.description) |
||||
|
const [birthday, setBirthday] = React.useState<Date | null>(dino.birthday ? new Date(dino.birthday) : null); |
||||
|
const [last, setLast] = React.useState<Date | null>(dino.last ? new Date(dino.last) : null); |
||||
|
|
||||
|
const saveTodo=() => { |
||||
|
const newdino = { |
||||
|
name: name, |
||||
|
snames: snames, |
||||
|
surname: surname, |
||||
|
id: dino.id === "" ? Math.random().toString() : dino.id, |
||||
|
description: description, |
||||
|
birthday: birthday?.toISOString(), |
||||
|
last: last?.toISOString() |
||||
|
}; |
||||
|
setDino(newdino); |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<> |
||||
|
<DialogContent> |
||||
|
<Box component="form" |
||||
|
sx={{ |
||||
|
'& > :not(style)': { m: 2, width: '50ch' }, |
||||
|
}}> |
||||
|
<TextField |
||||
|
autoFocus |
||||
|
id="name" |
||||
|
value={name} |
||||
|
label="Name" |
||||
|
onChange={e =>setName(e.target.value)} |
||||
|
/> |
||||
|
<TextField |
||||
|
id="snames" |
||||
|
value={snames} |
||||
|
label="Second Names" |
||||
|
onChange={e =>setSnames(e.target.value)} |
||||
|
/> |
||||
|
<TextField |
||||
|
id="surname" |
||||
|
value={surname} |
||||
|
label="Surname" |
||||
|
onChange={e =>setSurname(e.target.value)} |
||||
|
/> |
||||
|
<TextField |
||||
|
id="description" |
||||
|
value={description} |
||||
|
label="Description" |
||||
|
onChange={e =>setDescription(e.target.value)} |
||||
|
/> |
||||
|
<DatePicker |
||||
|
mask={'__.__.____'} |
||||
|
label="Birthday" |
||||
|
value={birthday} |
||||
|
onChange={e =>setBirthday(e)} |
||||
|
renderInput={(params: any) => <TextField {...params} />} |
||||
|
/> |
||||
|
<DatePicker |
||||
|
mask={'__.__.____'} |
||||
|
label="Last Met" |
||||
|
value={last} |
||||
|
onChange={e =>setLast(e)} |
||||
|
renderInput={(params: any) => <TextField {...params} />} |
||||
|
/> |
||||
|
</Box> |
||||
|
</DialogContent> |
||||
|
<DialogActions> |
||||
|
<Button onClick={handleCancel}>Cancel</Button> |
||||
|
<Button onClick={saveTodo}>Save</Button> |
||||
|
</DialogActions> |
||||
|
</> |
||||
|
) |
||||
|
} |
||||
|
export function Dinos(){ |
||||
|
const [dinos, setDinos] = useLocalStorage<Dino[]>("dinos",[]); |
||||
|
|
||||
|
const [value, setValue] = useState(dinos[0]?.id); |
||||
|
|
||||
|
const handleChange = (event: React.SyntheticEvent, newValue: string) => { |
||||
|
setValue(newValue); |
||||
|
}; |
||||
|
|
||||
|
const deleteDino=(i: number) => |
||||
|
setDinos([...dinos.slice(0,i), |
||||
|
...dinos.slice(i+1)]); |
||||
|
|
||||
|
const setDino= (dino: Dino) => { |
||||
|
handleClose(); |
||||
|
setDinos([...dinos, dino]); |
||||
|
} |
||||
|
|
||||
|
const [open, setOpen] = useState(false); |
||||
|
const handleClickOpen = () => { |
||||
|
setOpen(true); |
||||
|
}; |
||||
|
const handleClose = () => { |
||||
|
setOpen(false); |
||||
|
}; |
||||
|
|
||||
|
const [open2, setOpen2] = useState(false); |
||||
|
const [edit, setEdit] = useState<Dino>({name: "", surname: "", description: "", id: "", snames: ""}); |
||||
|
const [editI, setEditI] = useState<number>(0); |
||||
|
const handleClickOpen2 = (dino: Dino, i: number) => { |
||||
|
setOpen2(true); |
||||
|
setEdit(dino); |
||||
|
setEditI(i); |
||||
|
}; |
||||
|
const handleClose2 = () => { |
||||
|
setOpen2(false); |
||||
|
}; |
||||
|
|
||||
|
const editDino= (dino: Dino) => { |
||||
|
handleClose2(); |
||||
|
setDinos([...dinos.slice(0,editI), |
||||
|
dino, |
||||
|
...dinos.slice(editI+1)]); |
||||
|
} |
||||
|
return( |
||||
|
<div style={{height: "100%", minHeight: 0, display: "flex", flexDirection: "column"}}> |
||||
|
<Typography variant="h4">Dinos</Typography> |
||||
|
<Box sx={{ display: "flex", flexGrow: 1, bgcolor: 'background.paper', height: "100%", minHeight: 0}}> |
||||
|
<Tabs orientation="vertical" |
||||
|
variant="scrollable" |
||||
|
value={value} |
||||
|
onChange={handleChange} |
||||
|
sx={{ borderRight: 1, borderColor: 'divider'}}> |
||||
|
{dinos.sort((a,b) => `${a.name}${a.surname}`.localeCompare(`${b.name}${b.surname}`)).map((dino) => |
||||
|
<Tab key={dino.id} label={`${dino.name} ${dino.surname.charAt(0)}.`} value={dino.id}/> |
||||
|
)} |
||||
|
<Button onClick={handleClickOpen}>+ Dino</Button> |
||||
|
</Tabs> |
||||
|
{dinos.map((dino, i) => |
||||
|
<TabPanel key={dino.id} selected={value} id={dino.id}> |
||||
|
<Box sx={{ marginLeft: 3}}> |
||||
|
<Card sx={{minHeight: "500px", minWidth: "1000px"}}> |
||||
|
<ShowDino dino={dino}/> |
||||
|
<CardActions> |
||||
|
<Button onClick={() => handleClickOpen2(dino, i)}><EditRoundedIcon/></Button> |
||||
|
<Button onClick={() => deleteDino(i)}><DeleteOutlineRoundedIcon/></Button> |
||||
|
</CardActions> |
||||
|
</Card> |
||||
|
</Box> |
||||
|
</TabPanel> |
||||
|
)} |
||||
|
<Dialog open={open} onClose={handleClose}> |
||||
|
<DialogTitle>New Dino</DialogTitle> |
||||
|
<ChangeDino dino={{id: "", name: "", surname: "", description: "", snames: ""}} setDino={setDino} handleCancel={handleClose}></ChangeDino> |
||||
|
</Dialog> |
||||
|
<Dialog open={open2} onClose={handleClose2}> |
||||
|
<DialogTitle>Edit Dino</DialogTitle> |
||||
|
<ChangeDino dino={edit} setDino={editDino} handleCancel={handleClose2}></ChangeDino> |
||||
|
</Dialog> |
||||
|
</Box> |
||||
|
</div> |
||||
|
) |
||||
|
} |
Loading…
Reference in new issue