Browse Source

Add Dino functionality

master
Maya Herrscher 3 years ago
parent
commit
9d544a68e3
  1. 28
      src/App.tsx
  2. 216
      src/components/Dinos.tsx
  3. 21
      src/components/Todos.tsx
  4. 2
      src/hooks/useLocalStorage.tsx

28
src/App.tsx

@ -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>
</>
);
}

216
src/components/Dinos.tsx

@ -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>
)
}

21
src/components/Todos.tsx

@ -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}>

2
src/hooks/useLocalStorage.tsx

@ -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(

Loading…
Cancel
Save