Add Dino functionality
This commit is contained in:
1 parent
ea59db58d3
commit
9d544a68e3
4 files changed
+244
-23
No files matched your search
+18
-10
@@ -1,10 +1,23 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import './App.css';
|
||||
import deLocale from 'date-fns/locale/de';
|
||||
import { AppBar, Box, Button, Paper, Toolbar, Typography } from '@mui/material';
|
||||
import { AppBar, Box, Button, createTheme, CssBaseline, Paper, ThemeProvider, Toolbar, Typography } from '@mui/material';
|
||||
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
||||
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
||||
import { Todos } from './components/Todos';
|
||||
import { Dinos } from './components/Dinos';
|
||||
|
||||
const theme = createTheme({
|
||||
palette: {
|
||||
mode: 'dark',
|
||||
primary: {
|
||||
main: '#aa00ff',
|
||||
},
|
||||
secondary: {
|
||||
main: '#00b0ff',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function Calendar(){
|
||||
return(
|
||||
@@ -12,14 +25,6 @@ return(
|
||||
)
|
||||
}
|
||||
|
||||
function Dinos(){
|
||||
return(
|
||||
<div>
|
||||
<Typography variant="h3">Dinos</Typography>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Overview(){
|
||||
return (
|
||||
<div style={{display: "flex", flexGrow: 1, flexDirection: "column", height: "100%", maxHeight: "100%"}}>
|
||||
@@ -41,6 +46,8 @@ function App() {
|
||||
const [page,setPage] = useState<string>("Overview");
|
||||
return (
|
||||
<>
|
||||
<ThemeProvider theme={theme}>
|
||||
<CssBaseline/>
|
||||
<LocalizationProvider dateAdapter={AdapterDateFns} locale={deLocale}>
|
||||
<AppBar>
|
||||
<Toolbar>
|
||||
@@ -70,6 +77,7 @@ function App() {
|
||||
</div>
|
||||
</div>
|
||||
</LocalizationProvider>
|
||||
</ThemeProvider>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, {useState } from 'react';
|
||||
import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Divider, List, ListItem, TextField, Typography } from '@mui/material';
|
||||
import { Box, Button, Checkbox, Dialog, DialogActions, DialogContent, DialogTitle, Divider, List, ListItem, 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';
|
||||
@@ -35,15 +35,11 @@ function ChangeTodo({todo, setTodo, handleCancel}: {todo: Todo, setTodo: (todo:
|
||||
setName(event.target.value);
|
||||
};
|
||||
|
||||
const [id, setId] = React.useState<string>(todo.id)
|
||||
|
||||
const [description, setDescription] = React.useState<string>(todo.description)
|
||||
const handleDescChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setDescription(event.target.value);
|
||||
};
|
||||
|
||||
const [done, setDone] = React.useState<boolean>(todo.done)
|
||||
|
||||
const [from, setFrom] = React.useState<Date | null>(todo.from ? new Date(todo.from) : null);
|
||||
const handleFrom = (newValue: Date | null) => {
|
||||
setFrom(newValue);
|
||||
@@ -58,8 +54,8 @@ function ChangeTodo({todo, setTodo, handleCancel}: {todo: Todo, setTodo: (todo:
|
||||
const saveTodo=() => {
|
||||
const newtodo = {
|
||||
name: name,
|
||||
id: id === "" ? Math.random().toString() : id,
|
||||
done: done,
|
||||
id: todo.id === "" ? Math.random().toString() : todo.id,
|
||||
done: todo.done,
|
||||
description: description,
|
||||
to: to?.toISOString(),
|
||||
from: from?.toISOString()
|
||||
@@ -75,6 +71,7 @@ function ChangeTodo({todo, setTodo, handleCancel}: {todo: Todo, setTodo: (todo:
|
||||
'& > :not(style)': { m: 2, width: '50ch' },
|
||||
}}>
|
||||
<TextField
|
||||
autoFocus
|
||||
id="name"
|
||||
value={name}
|
||||
label="Name"
|
||||
@@ -117,7 +114,7 @@ export function Todos({style}: {style?: any}) {
|
||||
{name: todo.name, id: todo.id, done: done, description: todo.description, to: todo.to, from: todo.from},
|
||||
...todos.slice(i+1)]);
|
||||
|
||||
const deleteTodo=(i: number,todo: Todo) =>
|
||||
const deleteTodo=(i: number) =>
|
||||
setTodos([...todos.slice(0,i),
|
||||
...todos.slice(i+1)]);
|
||||
|
||||
@@ -159,15 +156,15 @@ const editTodo= (todo: Todo) => {
|
||||
<Button onClick={handleClickOpen}>Add Todo</Button>
|
||||
<List>
|
||||
{todos.map((todo, i) =>
|
||||
<>
|
||||
<div key={todo.id}>
|
||||
<Box sx={{display: "flex", flexDirection: "columns"}}>
|
||||
<TodoItem key={todo.id} todo={todo}/>
|
||||
<input type="checkbox" checked={todo.done} onChange={(e) => setDone(i, todo,e.target.checked)}></input>
|
||||
<Checkbox checked={todo.done} onChange={(e) => setDone(i, todo,e.target.checked)}></Checkbox>
|
||||
<Button onClick={() => handleClickOpen2(todo, i)}><EditRoundedIcon/></Button>
|
||||
<Button onClick={() => deleteTodo}><DeleteOutlineRoundedIcon/></Button>
|
||||
<Button onClick={() => deleteTodo(i)}><DeleteOutlineRoundedIcon/></Button>
|
||||
</Box>
|
||||
{(i + 1) < todos.length && <Divider/>}
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</List>
|
||||
<Dialog open={open} onClose={handleClose}>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
function useLocalStorage<T>(storageKey: string, fallbackState: T): [T, (val: T) => void] {
|
||||
const [value, setValue] = useState(
|
||||
|
||||
Reference in new issue
Block a user