Add income and result card.

This commit is contained in:
Niklas Meinzer
2024-05-20 22:29:35 +02:00
parent e847deecdf
commit 17c1435c6a
8 changed files with 252 additions and 15 deletions

13
package-lock.json generated
View File

@@ -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",

View File

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

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

View File

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

View File

@@ -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 </StatLabel>
<StatNumber>{relativeRent.toFixed(2)} </StatNumber>
</Stat>
</StatGroup>
</CardBody>;
}
return <Card>
{body}
</Card>
}