Compare commits

...

10 Commits

Author SHA1 Message Date
bb5fa0133f Adjust flat data for Bieterunde 2025 2025-09-18 14:57:11 +02:00
Niklas Meinzer
321a11367e Add python script to export data from excel 2024-11-19 08:13:32 +01:00
Niklas Meinzer
02d5c5f1ca Switch to use external data 2024-11-19 08:12:37 +01:00
Niklas Meinzer
ac8436bcd3 Change min rent calculation 2024-11-12 08:47:24 +01:00
Niklas Meinzer
ea33a0c95c Change Results panel 2024-11-09 21:24:21 +01:00
Niklas Meinzer
6696575a0e fix wording 2024-11-09 21:04:51 +01:00
Niklas Meinzer
540ba03f27 fix flat data 2024-11-09 21:04:14 +01:00
Niklas Meinzer
7099d6b3e1 Adjust added cost to 1.50 € and change some wording 2024-11-02 22:07:45 +01:00
Niklas Meinzer
243ca18eb5 fix rent initial values 2024-10-04 12:05:39 +02:00
Niklas Meinzer
4a0f47f03b Change range description from relative rent to absolute rent 2024-10-04 11:59:02 +02:00
6 changed files with 193 additions and 115 deletions

23
prepareFlatData.py Normal file
View File

@@ -0,0 +1,23 @@
from pandas import read_excel
import json
PATH = "/home/niklas/ownCloud/wohpro/04_AGs/04_AG_Finanzen/Finanzierungsplan MHS/2025-09-11_FP_Allmende_AG_Treffen.xlsx"
OUTPUT_PATH = "./rent_data.json"
if __name__ == "__main__":
df = read_excel(PATH, sheet_name="Solimieten Daten Onlinetool")
data = {}
for index, row in df.iterrows():
data[row["Wohneinheit"]] = {
"size_private": row["Zahlfläche privat (m²)"],
"size_shared": row["Zahlfläche intern"],
"min_rent": row["Mindestmiete"],
"free_rent": row["Standardmiete frei"],
"wbs_rent": row["Standardmiete WBS"],
}
with open(OUTPUT_PATH, "w") as f:
json.dump(data, f)

7
pyproject.toml Normal file
View File

@@ -0,0 +1,7 @@
[project]
name = "allmende_solimieten"
version = "0.1.0"
dependencies = [
"pandas[excel]",
]
requires-python = ">=3.12"

View File

@@ -1,4 +1,4 @@
import { React, useState } from 'react'; import { React, useState, useEffect } from 'react';
import { import {
ChakraProvider, ChakraProvider,
@@ -12,20 +12,22 @@ import {
useColorModeValue, useColorModeValue,
OrderedList, OrderedList,
ListItem, ListItem,
Alert,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { FlatSelectionCard, FlatDetailsCard, SelfEvaluationCard, ResultsCard } from './Solimieten'; import { FlatSelectionCard, FlatDetailsCard, SelfEvaluationCard, ResultsCard } from './Solimieten';
import { Nav } from './Nav'; import { Nav } from './Nav';
import { minRent, maxRent, minRentFactor } from './Data';
function App() { function App() {
const [selectedFlat, setSelectedFlat] = useState(); const [selectedFlat, setSelectedFlat] = useState();
const [selectedRoom, setSelectedRoom] = useState(); const [selectedRoom, setSelectedRoom] = useState();
const [numAdults, setNumAdults] = useState(1);
const [rent, setRent] = useState(0); const [rent, setRent] = useState(0);
const [flatRent, setFlatRent] = useState();
const theme = extendTheme({ const theme = extendTheme({
"colors": { "colors": {
@@ -44,7 +46,30 @@ function App() {
} }
}); });
useEffect(() => {
setFlatRent(null);
if (selectedFlat && (selectedFlat.wgRoomList.length === 0 || selectedRoom)) {
console.log("Recalculating Rent...");
var commonAreaShare = 60;
var kitchenCost = 50;
var sizePrivate = selectedFlat.sizePrivate;
var internalAreaShare = 0;
if (selectedFlat.wgRoomList.length > 0) {
internalAreaShare = selectedFlat.calcInternalAreaShare(selectedRoom);
sizePrivate = selectedRoom.size;
kitchenCost = kitchenCost / selectedFlat.wgRoomList.length;
}
var newRent = {
minCovering: (sizePrivate + internalAreaShare) * minRent + kitchenCost + commonAreaShare,
maxCovering: (sizePrivate + internalAreaShare) * maxRent + kitchenCost + commonAreaShare
}
newRent.min = newRent.minCovering * minRentFactor;
setFlatRent(newRent);
}
}, [selectedFlat, selectedRoom])
return ( return (
@@ -55,7 +80,7 @@ function App() {
<Stack maxWidth={1200}> <Stack maxWidth={1200}>
<Box p={6} borderRadius="lg" bg={useColorModeValue('gray.100', 'gray.200')}> <Box p={6} borderRadius="lg" bg={useColorModeValue('gray.100', 'gray.200')}>
<Text> <Text>
<Heading>Allemende Solimieten-Helferlein</Heading> <Heading>Allmende Solimieten-Helferlein</Heading>
Im Rahmen des Konzept für solidarische Mieten, kann jede Partei in der Allmende ihre Miethöhe selbst bestimmen. Im Rahmen des Konzept für solidarische Mieten, kann jede Partei in der Allmende ihre Miethöhe selbst bestimmen.
Dieses Tool soll als Orientierungshilfe bei der Selbsteinschätzung dienen. Dieses Tool soll als Orientierungshilfe bei der Selbsteinschätzung dienen.
@@ -69,19 +94,20 @@ function App() {
<ListItem>Nun siehst du den daraus resultierenden Mietpreis absolut und auf den Quadratmeter gerechnet.</ListItem> <ListItem>Nun siehst du den daraus resultierenden Mietpreis absolut und auf den Quadratmeter gerechnet.</ListItem>
</OrderedList> </OrderedList>
</Box> </Box>
<SimpleGrid pt={5} columns={{ base: 1, md: 2, lg: 2 }} spacing={4}> <SimpleGrid pt={5} columns={{ base: 1, md: 2, lg: 2 }} spacing={4}>
<Heading>Wohnung</Heading> <Heading>Wohnung</Heading>
<Box></Box> <Box></Box>
<FlatSelectionCard setSelectedFlat={setSelectedFlat} onRoomSelected={setSelectedRoom} onNumAdultsSelected={setNumAdults} /> <FlatSelectionCard setSelectedFlat={setSelectedFlat} onRoomSelected={setSelectedRoom} />
<FlatDetailsCard flat={selectedFlat} room={selectedRoom} numAdults={numAdults} /> <FlatDetailsCard flat={selectedFlat} room={selectedRoom} flatRent={flatRent} />
<Heading>Selbsteinschätzung</Heading> <Heading>Selbsteinschätzung</Heading>
<Box></Box> <Box></Box>
<SelfEvaluationCard rent={rent} setRent={setRent} /> <SelfEvaluationCard rent={rent} setRent={setRent} />
<ResultsCard rent={rent} flat={selectedFlat} room={selectedRoom} /> <ResultsCard rent={rent} flat={selectedFlat} room={selectedRoom} flatRent={flatRent} />
</SimpleGrid> </SimpleGrid>
</Stack> </Stack>
</Center> </Center>

View File

@@ -1,8 +1,9 @@
import rentData from './rent_data.json';
class Flat { class Flat {
constructor(name, numRooms, sizePrivate, isWbs = false, isAccessible = false, wgRoomList = null) { constructor(name, numRooms, isWbs = false, isAccessible = false, wgRoomList = null, combineRooms = null) {
this.name = name; this.name = name;
this.numRooms = numRooms; this.numRooms = numRooms;
this.sizePrivate = sizePrivate; this.sizePrivate = 0;
this.isWbs = isWbs; this.isWbs = isWbs;
this.sizeShared = 0; this.sizeShared = 0;
// Normal flats have as many people as rooms // Normal flats have as many people as rooms
@@ -10,11 +11,22 @@ class Flat {
if (!wgRoomList) { if (!wgRoomList) {
this.wgRoomList = []; this.wgRoomList = [];
this.numPeople = numRooms; this.numPeople = numRooms;
var idList = combineRooms ? combineRooms : [name];
this.minRent = 0;
this.wbsRent = 0;
this.freeRent = 0;
for (var i = 0; i < idList.length; i++) {
this.minRent += rentData[idList[i]].min_rent;
this.wbsRent += rentData[idList[i]].wbs_rent;
this.freeRent += rentData[idList[i]].free_rent;
this.sizePrivate += rentData[idList[i]].size_private;
}
} else { } else {
this.wgRoomList = wgRoomList; this.wgRoomList = wgRoomList;
this.sizeShared = this.sizePrivate; this.sizeShared = this.sizePrivate;
for (var i = 0; i < this.wgRoomList.length; i++) { for (var j = 0; j < this.wgRoomList.length; j++) {
this.sizeShared -= this.wgRoomList[i].size; this.sizeShared -= this.wgRoomList[j].size;
} }
this.numPeople = numRooms - 1; this.numPeople = numRooms - 1;
} }
@@ -45,10 +57,16 @@ class Flat {
} }
class Room { class Room {
constructor(name, size, numPeople = 1) { constructor(name, numPeople = 1, id = null) {
this.name = name; this.name = name;
this.size = size;
this.numPeople = numPeople; this.numPeople = numPeople;
var key = id ? id : name;
this.sizePrivate = rentData[key].size_private;
this.sizeShared = rentData[key].size_shared;
this.minRent = rentData[key].min_rent;
this.freeRent = rentData[key].free_rent;
this.wbsRent = rentData[key].wbs_rent;
} }
print() { print() {
@@ -59,56 +77,58 @@ class Room {
export const flatData = { export const flatData = {
"north": { "north": {
0: [ 0: [
new Flat("W 0.1 (WG)", 4, 84.834, false, false, [ new Flat("W 0.1 (WG)", 4, false, false, [
new Room("0.1 02", 12.523), new Room("0.1 03", 12.102), new Room("0.1 04", 14.746) new Room("0.1.02"), new Room("0.1.03"), new Room("0.1.04")
]), ]),
new Flat("W 0.2", 2, 53.453, true), new Flat("0.2", 2, true),
new Flat("W 0.3", 3, 63.498, true) new Flat("0.3", 3, true)
], ],
1: [ 1: [
new Flat("W 1.1", 4, 84.794, true), new Flat("1.1", 4, true),
new Flat("W 1.2", 1, 36.469, true), new Flat("1.2", 1, true),
new Flat("W 1.3 (WG)", 4, 63.128, true, false, [ new Flat("W 1.3 (WG)", 4, true, false, [
new Room("1.3 02", 11.434), new Room("1.3 03", 11.245), new Room("1.3 04", 11.77) new Room("1.3.02"), new Room("1.3.03"), new Room("1.3.04")
]) ])
], ],
2: [ 2: [
new Flat("W 2.1", 4, 84.794, true), new Flat("2.1", 4, true),
new Flat("W 2.2", 2, 46.261, true), new Flat("2.2", 2, true),
new Flat("W 2.3 (Cluster)", 5, 154.196, true, true, [ new Flat("W 2.3 (Cluster)", 5, true, true, [
new Room("1 Person", 28.774), new Room("2 Personen", 46.32, 2), new Room("1 Person (rollstuhlgerecht)", 41.814) new Room("1 Person", 1, "2.3.02"), new Room("2 Personen", 2, "2.3.05"), new Room("1 Person (rollstuhlgerecht)", 1, "2.3.09")
]), ]),
new Flat("W 2.4", 2, 64.265, true, true) new Flat("2.4", 2, true, true)
], ],
3: [ 3: [
new Flat("W 3.1", 4, 84.794), new Flat("3.1", 4),
new Flat("W 3.2 (Cluster)", 5, 154.97, true, true, [ new Flat("W 3.2 (Cluster)", 5, true, true, [
new Room("1 Person", 28.531), new Room("2 Personen", 47.146, 2), new Room("1 Person (rollstuhlgerecht)", 44.036) new Room("1 Person", 1, "3.2.02"), new Room("2 Personen", 2, "3.2.05"), new Room("1 Person (rollstuhlgerecht)", 1, "3.2.09")
]), ]),
new Flat("W 3.3", 3, 63.128, true) new Flat("3.3", 3, true, false, null, ["3.3.02", "3.3.03", "3.3.04"])
] ]
}, },
"south": { "south": {
0: [ 0: [
new Flat("W 0.4", 2, 54.905, true), new Flat("0.4", 2, true),
new Flat("W 0.5", 4, 83.416, true), new Flat("0.5", 4, true),
new Flat("W 0.6", 5, 107.733, true), new Flat("0.6", 5, true),
], ],
1: [ 1: [
new Flat("W 1.4", 2, 59.442), new Flat("1.4", 2),
new Flat("W 1.5 (WG)", 5, 89.209, true, false, new Flat("W 1.5 (WG)", 5, true, false,
[new Room("1.5 02", 15.448), new Room("1.5 05", 11.489), new Room("1.5 06", 13.462)] [new Room("1.5.02"), new Room("1.5.03"), new Room("1.5.05"), new Room("1.5.06")]
), ),
new Flat("W 1.6.0", 1, 30.431), new Flat("1.6.2", 1),
new Flat("W 1.6", 5, 108.761), new Flat("1.6.1", 5),
], ],
2: [ 2: [
new Flat("W 2.5", 2, 58.882), new Flat("2.5", 2, true),
new Flat("W 2.6", 4, 89.853, true), new Flat("2.6", 4, true),
new Flat("W 2.7", 5, 101.533) new Flat("2.7", 5)
] ]
} }
} }
const addedCost = 1.2; const addedCost = 1.5;
export const minRent = 9.45 + addedCost; export const minRent = 9.45 + addedCost;
export const maxRent = 13.06 + addedCost; export const maxRent = 13.06 + addedCost;
export const minRentFactor = 0.85;

View File

@@ -14,7 +14,6 @@ import {
StatNumber, StatNumber,
StatGroup, StatGroup,
Select, Select,
Progress,
NumberInput, NumberInput,
NumberInputField, NumberInputField,
Slider, Slider,
@@ -22,12 +21,14 @@ import {
SliderMark, SliderMark,
SliderTrack, SliderTrack,
SliderThumb, SliderThumb,
Tooltip Tooltip,
Alert,
AlertIcon
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { flatData, minRent, maxRent } from './Data'; import { flatData } from './Data';
export function FlatSelectionCard({ setSelectedFlat, onRoomSelected, onNumAdultsSelected }) { export function FlatSelectionCard({ setSelectedFlat, onRoomSelected }) {
const [levelOptions, setLevelOption] = useState([{ value: 0, label: "EG" }, { value: 1, label: "1. OG" }, { value: 2, label: "2. OG" }, { value: 3, label: "3. OG" }]); const [levelOptions, setLevelOption] = useState([{ value: 0, label: "EG" }, { value: 1, label: "1. OG" }, { value: 2, label: "2. OG" }, { value: 3, label: "3. OG" }]);
const [flatOptions, setFlatOptions] = useState([]); const [flatOptions, setFlatOptions] = useState([]);
const [roomOptions, setRoomOptions] = useState([]); const [roomOptions, setRoomOptions] = useState([]);
@@ -68,9 +69,6 @@ export function FlatSelectionCard({ setSelectedFlat, onRoomSelected, onNumAdults
onRoomSelected(roomOptions[e.target.value]); onRoomSelected(roomOptions[e.target.value]);
} }
function numAdultsSelected(e) {
onNumAdultsSelected(e.target.value);
}
return <Card> return <Card>
<CardHeader> <CardHeader>
<Heading size='md'>Wohnungsauswahl</Heading> <Heading size='md'>Wohnungsauswahl</Heading>
@@ -88,47 +86,41 @@ export function FlatSelectionCard({ setSelectedFlat, onRoomSelected, onNumAdults
{flatOptions.map((flat, index) => <option value={index} >{flat.print()}</option>)} {flatOptions.map((flat, index) => <option value={index} >{flat.print()}</option>)}
</Select> </Select>
{roomOptions.length > 0 ? (<Select placeholder='Zimmer auswählen' onChange={roomSelected}> {roomOptions.length > 0 ? (<Select placeholder='Zimmer auswählen' onChange={roomSelected}>
{roomOptions.map((room, index) => <option value={index} >{room.print()} ({room.size} )</option>)} {roomOptions.map((room, index) => <option value={index} >{room.print()} ({room.sizePrivate.toFixed(2)} )</option>)}
</Select>) : null} </Select>) : null}
<Select placeholder='Anzahl Erwachsene' onChange={numAdultsSelected}>
<option value="1">1 erwachsene Person</option>
<option value="2">2 erwachsene Personen</option>
</Select>
</Stack> </Stack>
</CardBody> </CardBody>
</Card > </Card >
} }
export function FlatDetailsCard({ flat, room, numAdults }) { export function FlatDetailsCard({ flat, room, flatRent }) {
var body = <CardBody> var body = <CardBody>
Bitte auswählen Bitte auswählen
</CardBody>; </CardBody>;
var badges = ""; var badges = "";
var kitchenCost = 50;
var commonAreaShare = 60 * numAdults;
if (flat && (room || flat.wgRoomList.length === 0)) { if (flat && (flat.wgRoomList.length === 0 || room) && flatRent) {
var sizePrivate = flat.sizePrivate; var freeRent = flat.freeRent;
var wbsRent = flat.wbsRent;
var minRent = flat.minRent;
if (room) { if (room) {
sizePrivate = room.size; freeRent = room.freeRent;
kitchenCost = kitchenCost / flat.wgRoomList.length; wbsRent = room.wbsRent;
minRent = room.minRent;
} }
var sizeSharedBox = null; var sizeSharedBox = null;
var internalAreaShare = flat.calcInternalAreaShare(room);
var totalSizeToPay = flat.calcTotalPayedArea(room);
if (flat.wgRoomList.length > 0) { if (flat.wgRoomList.length > 0) {
var totalSizeToPay = room.sizePrivate + room.sizeShared;
sizeSharedBox = [ sizeSharedBox = [
<Box> <Box>
<Heading size='xs' textTransform='uppercase'> <Heading size='xs' textTransform='uppercase'>
Anteil Interne Gemeinschaftsfläche (WG und Cluster) Anteil Interne Gemeinschaftsfläche (WG und Cluster)
</Heading> </Heading>
<Text pt='2' fontSize='sm'> <Text pt='2' fontSize='sm'>
{internalAreaShare.toFixed(2)} {room.sizeShared.toFixed(2)}
</Text> </Text>
</Box >, </Box >,
<Box> <Box>
@@ -136,7 +128,7 @@ export function FlatDetailsCard({ flat, room, numAdults }) {
Zahlfläche Zahlfläche
</Heading> </Heading>
<Text pt='2' fontSize='sm'> <Text pt='2' fontSize='sm'>
{sizePrivate.toFixed(2)} + {internalAreaShare.toFixed(2)} (WG/Cluster-Fläche) {room.sizePrivate.toFixed(2)} + {room.sizeShared.toFixed(2)} (WG/Cluster-Fläche)
</Text> </Text>
<Text pt={3} size='s' fontWeight='bold'>Gesamt: {totalSizeToPay.toFixed(2)} </Text> <Text pt={3} size='s' fontWeight='bold'>Gesamt: {totalSizeToPay.toFixed(2)} </Text>
</Box> </Box>
@@ -158,38 +150,39 @@ export function FlatDetailsCard({ flat, room, numAdults }) {
</Box> </Box>
<Box> <Box>
<Heading size='xs' textTransform='uppercase'> <Heading size='xs' textTransform='uppercase'>
Zimmeranzahl und Gesamtfläche Zimmeranzahl {room ? "" : "und Gesamtfläche"}
</Heading> </Heading>
<Text pt='2' fontSize='sm'> <Text pt='2' fontSize='sm'>
{flat.numRooms} Zimmer, {flat.sizePrivate.toFixed(2)} {flat.numRooms} Zimmer {room ? "" : " " + flat.sizePrivate.toFixed(2) + "m²"}
</Text> </Text>
</Box> </Box>
{sizeSharedBox} {sizeSharedBox}
<Box>
<Heading size='xs' textTransform='uppercase'>
Standardmiete WBS
</Heading>
<Text fontSize="xs">Die Standardmiete ergibt sich aus dem WBS Satz für die private Fläche, den Betriebskosten, der Küchen-Nutzungspauschale, den Abschlägen für Strom und Wasser sowie einem Gemeinschaftsflächenbeitrag und wird WBS-Wohnungen/Zimmern automatisch zugewiesen, sollte die entsprechende Partei kein Gebot abgeben. <b>Mit der Standardmiete wäre das gesamte Haus finanziert, wenn wir keine Bieterunden durchführen würden.</b></Text>
<Text pt='2' fontSize='xl' fontWeight='bold'>
{(wbsRent).toFixed(2)}
</Text>
</Box>
<Box>
<Heading size='xs' textTransform='uppercase'>
Standardmiete freifinanziert {flat.isWbs ? "(zum Vergleich)" : ""}
</Heading>
<Text fontSize="xs">Die Standardmiete freifinanziert, wird analog zur Standardmiete WBS berechnet, wobei der Flächenpreis für freifinanzierte Wohnungen genommen wird. Sie wird frei finanzierten Wohnungen/Zimmern automatisch zugewiesen, sollte die entsprechende Partei kein Gebot abgeben. <b>Mit der Standardmiete wäre das gesamte Haus finanziert, wenn wir keine Bieterunden durchführen würden.</b></Text>
<Text pt='2' fontSize='xl' fontWeight='bold'>
{(freeRent).toFixed(2)}
</Text>
</Box>
<Box> <Box>
<Heading size='xs' textTransform='uppercase'> <Heading size='xs' textTransform='uppercase'>
Mindestmiete Mindestmiete
</Heading> </Heading>
<Text fontSize="xs">Die Mindestmiete ergibt sich aus dem WBS Satz für die private Fläche (9,45 /), den Nebenkosten (1,20 /) und der Küchen-Nutzungspauschale von 50 pro Küche (in Clustern und WGs auf Parteien aufgeteilt)</Text> <Text fontSize="xs">Die Mindestmiete stellt die untere Grenze dar, die für diese Wohnung geboten werden darf und berechnet sich aus der Standardmiete WBS - 15 %
<Text pt='2' fontSize='xl' fontWeight='bold'>
{((sizePrivate + internalAreaShare) * minRent + kitchenCost).toFixed(2)}
</Text> </Text>
</Box>
<Box>
<Heading size='xs' textTransform='uppercase'>
Deckungsmiete WBS
</Heading>
<Text fontSize="xs">Die Deckungsmiete beinhaltet einen Beitrag von 60 pro erwachsener Person für die Gemeinschaftsflächen</Text>
<Text pt='2' fontSize='xl' fontWeight='bold'> <Text pt='2' fontSize='xl' fontWeight='bold'>
{((sizePrivate + internalAreaShare) * minRent + kitchenCost + commonAreaShare).toFixed(2)} {(minRent).toFixed(2)}
</Text>
</Box>
<Box>
<Heading size='xs' textTransform='uppercase'>
Deckungsmiete freifinanziert {flat.isWbs ? "(zum Vergleich)" : ""}
</Heading>
<Text fontSize="xs">Das ist die Miete, die für diese Wohnung ohne solidarischen Ausgleich anfallen würde{flat.isWbs ? ", wenn Sie frei finanziert wäre " : " "}und ergibt sich aus 13,06 / plus 1,20 / Nebenkosten und Gemeinschaftsflächen-Pauschale.</Text>
<Text pt='2' fontSize='xl' fontWeight='bold'>
{((sizePrivate + internalAreaShare) * maxRent + kitchenCost + commonAreaShare).toFixed(2)}
</Text> </Text>
</Box> </Box>
</Stack> </Stack>
@@ -223,7 +216,7 @@ export function SelfEvaluationCard({ rent, setRent }) {
const [sliderValue, setSliderValue] = useState(30) const [sliderValue, setSliderValue] = useState(30)
const [showTooltip, setShowTooltip] = useState(false) const [showTooltip, setShowTooltip] = useState(false)
const [income, setIncome] = useState(1000) const [income, setIncome] = useState(0)
const formatEuro = (val) => val + ' €'; const formatEuro = (val) => val + ' €';
const parseEuro = (val) => val.replace(/^€/, '') const parseEuro = (val) => val.replace(/^€/, '')
@@ -298,23 +291,43 @@ export function SelfEvaluationCard({ rent, setRent }) {
</Card> </Card>
} }
export function ResultsCard({ rent, flat, room }) { export function ResultsCard({ rent, flat, room, flatRent }) {
var body = <CardBody></CardBody> var body = <CardBody></CardBody>
if (flat && (room || flat.wgRoomList.length === 0)) { if (rent && flat && (room || flat.wgRoomList.length === 0) && flatRent) {
var _wbsRent = flat.wbsRent;
var _freeRent = flat.freeRent;
var _minRent = flat.minRent;
if (room) {
_wbsRent = room.wbsRent;
_freeRent = room.freeRent;
_minRent = room.minRent;
}
var totalSize = flat.calcTotalPayedArea(room) var totalSize = flat.calcTotalPayedArea(room)
var relativeRent = (rent) / totalSize;
var status = "error", text = "Dieses Gebot läge unter der Mindestmiete und ist nicht zulässig";
if (rent >= _minRent) {
status = 'info';
text = "Über der Mindestmiete. "
}
if (rent >= _wbsRent) {
status = 'success';
text = 'Über der Standardmiete WBS 🎉'
}
if (rent >= _freeRent) {
status = 'success';
text = 'Über der Standardmiete freifinanziert 🎉🎉🎉'
}
var relativeRent = rent / totalSize;
var rangePosition = ((relativeRent - minRent) / (maxRent - minRent)) * 100;
if (rangePosition < 0) { rangePosition = 0; }
if (rangePosition > 100) { rangePosition = 100; }
var color = "green";
if (rangePosition > 33) { color = "yellow"; }
if (rangePosition > 66) { color = "red"; }
body = <CardBody> body = <CardBody>
<Stack> <Stack>
<Text fontWeight="bold">
Das ergäbe eine Miete von:
</Text>
<StatGroup> <StatGroup>
<Stat> <Stat>
<StatLabel>Miete</StatLabel> <StatLabel>Warmmiete</StatLabel>
<StatNumber>{rent} </StatNumber> <StatNumber>{rent} </StatNumber>
</Stat> </Stat>
@@ -323,22 +336,10 @@ export function ResultsCard({ rent, flat, room }) {
<StatNumber>{relativeRent.toFixed(2)} </StatNumber> <StatNumber>{relativeRent.toFixed(2)} </StatNumber>
</Stat> </Stat>
</StatGroup> </StatGroup>
<Text> <Alert status={status}>
Im Folgenden siehst du, wo deine Miete auf der Spanne zwischen WBS-Satz und <AlertIcon />
frei finanzierten Wohnungen ohne Soli-Ausgleich liegen würde. {text}
</Text> </Alert>
<Progress colorScheme={color} size='sm' value={rangePosition} />
<StatGroup>
<Stat>
<StatLabel>WBS Miete</StatLabel>
<StatNumber>{minRent.toFixed(2)} </StatNumber>
</Stat>
<Stat>
<StatLabel>Max</StatLabel>
<StatNumber>{maxRent.toFixed(2)} </StatNumber>
</Stat>
</StatGroup>
</Stack> </Stack>
</CardBody>; </CardBody>;
} }

1
src/rent_data.json Normal file

File diff suppressed because one or more lines are too long