Add income and result card.
This commit is contained in:
13
package-lock.json
generated
13
package-lock.json
generated
@@ -8,6 +8,7 @@
|
||||
"name": "allmende-solimieten",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@chakra-ui/icons": "^2.1.1",
|
||||
"@chakra-ui/react": "^2.8.2",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
@@ -2313,6 +2314,18 @@
|
||||
"react": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@chakra-ui/icons": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/icons/-/icons-2.1.1.tgz",
|
||||
"integrity": "sha512-3p30hdo4LlRZTT5CwoAJq3G9fHI0wDc0pBaMHj4SUn0yomO+RcDRlzhdXqdr5cVnzax44sqXJVnf3oQG0eI+4g==",
|
||||
"dependencies": {
|
||||
"@chakra-ui/icon": "3.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@chakra-ui/system": ">=2.0.0",
|
||||
"react": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@chakra-ui/image": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@chakra-ui/image/-/image-2.1.0.tgz",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@chakra-ui/icons": "^2.1.1",
|
||||
"@chakra-ui/react": "^2.8.2",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
|
||||
BIN
public/logo.png
Normal file
BIN
public/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB |
112
src/App.js
112
src/App.js
@@ -3,7 +3,7 @@ import { React, useState } from 'react';
|
||||
import {
|
||||
ChakraProvider,
|
||||
Text,
|
||||
theme,
|
||||
extendTheme,
|
||||
Select,
|
||||
Card,
|
||||
CardHeader,
|
||||
@@ -11,11 +11,21 @@ import {
|
||||
CardBody,
|
||||
Center,
|
||||
SimpleGrid,
|
||||
Box,
|
||||
Stack,
|
||||
NumberInput,
|
||||
NumberInputField,
|
||||
Slider,
|
||||
SliderFilledTrack,
|
||||
SliderMark,
|
||||
SliderTrack,
|
||||
SliderThumb,
|
||||
Tooltip
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { FlatDetails } from './Solimieten';
|
||||
import { ColorModeSwitcher } from './ColorModeSwitcher';
|
||||
import { FlatDetails, ResultsCard } from './Solimieten';
|
||||
import { flatData } from './Data';
|
||||
import { Nav } from './Nav';
|
||||
|
||||
function App() {
|
||||
const [levelOptions, setLevelOption] = useState([{ value: 0, label: "EG" }, { value: 1, label: "1. OG" }, { value: 2, label: "2. OG" }, { value: 3, label: "3. OG" }]);
|
||||
@@ -23,6 +33,28 @@ function App() {
|
||||
const [selectedBuilding, setSelectedBuilding] = useState();
|
||||
const [selectedFlat, setSelectedFlat] = useState();
|
||||
|
||||
const [income, setIncome] = useState(0);
|
||||
|
||||
const [sliderValue, setSliderValue] = useState(30)
|
||||
const [showTooltip, setShowTooltip] = useState(false)
|
||||
|
||||
const theme = extendTheme({
|
||||
"colors": {
|
||||
"gray": {
|
||||
"50": "#F3FEE7",
|
||||
"100": "#DEFCBB",
|
||||
"200": "#C8FA8F",
|
||||
"300": "#B3F862",
|
||||
"400": "#9DF636",
|
||||
"500": "#88F50A",
|
||||
"600": "#6DC408",
|
||||
"700": "#529306",
|
||||
"800": "#366204",
|
||||
"900": "#1B3102"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function buildingSelected(e) {
|
||||
var newOptions;
|
||||
if (e.target.value === "south") {
|
||||
@@ -48,17 +80,26 @@ function App() {
|
||||
setSelectedFlat(flatOptions[index]);
|
||||
}
|
||||
|
||||
const formatEuro = (val) => val + ' €';
|
||||
const parseEuro = (val) => val.replace(/^€/, '')
|
||||
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<ChakraProvider theme={theme}>
|
||||
<Nav></Nav>
|
||||
<Center>
|
||||
<SimpleGrid columns={2} spacing={4}>
|
||||
<Heading>Wohnung</Heading>
|
||||
<Box></Box>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<Heading size='md'>Wohnungsauswahl</Heading>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<Text>View a summary of all your customers over the last month.</Text>
|
||||
<Stack spacing={4} w="500px">
|
||||
<Select placeholder='Gebäude auswählen' onChange={buildingSelected}>
|
||||
<option value='north'>Nordbau</option>
|
||||
<option value='south'>Südbau</option>
|
||||
@@ -69,9 +110,72 @@ function App() {
|
||||
<Select placeholder='Wohnung auswählen' onChange={flatSelected}>
|
||||
{flatOptions.map((flat, index) => <option value={index} >{flat.print()}</option>)}
|
||||
</Select>
|
||||
</Stack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<FlatDetails flat={selectedFlat} />
|
||||
|
||||
<Heading>Selbsteinschätzung</Heading>
|
||||
<Box></Box>
|
||||
|
||||
<Card>
|
||||
<CardBody maxW={500}>
|
||||
<Stack spacing={3}>
|
||||
<Text>Wie hoch ist euer/dein Haushaltsnetto? Beachtet dabei alle regelmäßigen Einkünfte wie Gehalt, Rente, Mieteinkünfte oder Kapitalerträge </Text>
|
||||
<NumberInput
|
||||
onChange={(valueString) => setIncome(parseEuro(valueString))}
|
||||
value={formatEuro(income)}
|
||||
>
|
||||
<NumberInputField />
|
||||
</NumberInput>
|
||||
|
||||
<Text>Wie viel Prozent eures/deines Nettoeinkommens kannst du für Miete aufbringen?</Text>
|
||||
<Slider
|
||||
id='slider'
|
||||
defaultValue={30}
|
||||
min={10}
|
||||
max={50}
|
||||
mb={5}
|
||||
colorScheme='teal'
|
||||
onChange={(v) => setSliderValue(v)}
|
||||
onMouseEnter={() => setShowTooltip(true)}
|
||||
onMouseLeave={() => setShowTooltip(false)}
|
||||
>
|
||||
<SliderMark value={10} mt='1' ml='-2.5' fontSize='sm'>
|
||||
10%
|
||||
</SliderMark>
|
||||
<SliderMark value={20} mt='1' ml='-2.5' fontSize='sm'>
|
||||
20%
|
||||
</SliderMark>
|
||||
<SliderMark value={30} mt='1' ml='-2.5' fontSize='sm'>
|
||||
30%
|
||||
</SliderMark>
|
||||
<SliderMark value={40} mt='1' ml='-2.5' fontSize='sm'>
|
||||
40%
|
||||
</SliderMark>
|
||||
<SliderMark value={50} mt='1' ml='-2.5' fontSize='sm'>
|
||||
50%
|
||||
</SliderMark>
|
||||
<SliderTrack>
|
||||
<SliderFilledTrack />
|
||||
</SliderTrack>
|
||||
<Tooltip
|
||||
hasArrow
|
||||
bg='teal.500'
|
||||
color='white'
|
||||
placement='top'
|
||||
isOpen={showTooltip}
|
||||
label={`${sliderValue}%`}
|
||||
>
|
||||
<SliderThumb />
|
||||
</Tooltip>
|
||||
|
||||
|
||||
</Slider>
|
||||
</Stack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<ResultsCard income={income} percentage={sliderValue} flat={selectedFlat} />
|
||||
</SimpleGrid>
|
||||
</Center>
|
||||
</ChakraProvider >
|
||||
|
||||
88
src/Nav.js
Normal file
88
src/Nav.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import { ReactNode } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
Avatar,
|
||||
Link,
|
||||
Button,
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuList,
|
||||
MenuItem,
|
||||
MenuDivider,
|
||||
useDisclosure,
|
||||
useColorModeValue,
|
||||
Stack,
|
||||
useColorMode,
|
||||
Center,
|
||||
Image,
|
||||
} from '@chakra-ui/react';
|
||||
import { MoonIcon, SunIcon } from '@chakra-ui/icons';
|
||||
|
||||
const NavLink = ({ children }) => (
|
||||
<Link
|
||||
px={2}
|
||||
py={1}
|
||||
rounded={'md'}
|
||||
_hover={{
|
||||
textDecoration: 'none',
|
||||
bg: useColorModeValue('gray.200', 'gray.700'),
|
||||
}}
|
||||
href={'#'}>
|
||||
{children}
|
||||
</Link>
|
||||
);
|
||||
|
||||
export function Nav() {
|
||||
const { colorMode, toggleColorMode } = useColorMode();
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
return (
|
||||
<>
|
||||
<Box mb="10px" bg={useColorModeValue('gray.100', 'gray.900')} px={4}>
|
||||
<Flex h={16} alignItems={'center'} justifyContent={'space-between'}>
|
||||
<Box><Image src="logo.png" w='120px'></Image></Box>
|
||||
|
||||
<Flex alignItems={'center'}>
|
||||
<Stack direction={'row'} spacing={7}>
|
||||
<Button onClick={toggleColorMode}>
|
||||
{colorMode === 'light' ? <MoonIcon /> : <SunIcon />}
|
||||
</Button>
|
||||
|
||||
{/* <Menu>
|
||||
<MenuButton
|
||||
as={Button}
|
||||
rounded={'full'}
|
||||
variant={'link'}
|
||||
cursor={'pointer'}
|
||||
minW={0}>
|
||||
<Avatar
|
||||
size={'sm'}
|
||||
src={'https://avatars.dicebear.com/api/male/username.svg'}
|
||||
/>
|
||||
</MenuButton>
|
||||
<MenuList alignItems={'center'}>
|
||||
<br />
|
||||
<Center>
|
||||
<Avatar
|
||||
size={'2xl'}
|
||||
src={'https://avatars.dicebear.com/api/male/username.svg'}
|
||||
/>
|
||||
</Center>
|
||||
<br />
|
||||
<Center>
|
||||
<p>Username</p>
|
||||
</Center>
|
||||
<br />
|
||||
<MenuDivider />
|
||||
<MenuItem>Your Servers</MenuItem>
|
||||
<MenuItem>Account Settings</MenuItem>
|
||||
<MenuItem>Logout</MenuItem>
|
||||
</MenuList>
|
||||
</Menu> */}
|
||||
</Stack>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -7,7 +7,13 @@ import {
|
||||
StackDivider,
|
||||
Box,
|
||||
Text,
|
||||
Badge
|
||||
Badge,
|
||||
Stat,
|
||||
StatLabel,
|
||||
StatNumber,
|
||||
StatHelpText,
|
||||
StatArrow,
|
||||
StatGroup
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
export function FlatDetails({ flat }) {
|
||||
@@ -71,3 +77,28 @@ export function FlatDetails({ flat }) {
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export function ResultsCard({ income, percentage, flat }) {
|
||||
var body = <CardBody></CardBody>
|
||||
if (flat) {
|
||||
var rent = income * percentage / 100;
|
||||
var relativeRent = rent / flat.sizePrivate;
|
||||
body = <CardBody>
|
||||
<StatGroup>
|
||||
<Stat>
|
||||
<StatLabel>Miete</StatLabel>
|
||||
<StatNumber>{rent} €</StatNumber>
|
||||
</Stat>
|
||||
|
||||
<Stat>
|
||||
<StatLabel>Pro m²</StatLabel>
|
||||
<StatNumber>{relativeRent.toFixed(2)} €</StatNumber>
|
||||
</Stat>
|
||||
</StatGroup>
|
||||
</CardBody>;
|
||||
}
|
||||
|
||||
return <Card>
|
||||
{body}
|
||||
</Card>
|
||||
}
|
||||
Reference in New Issue
Block a user