Základní Pizza kalkulačka
This commit is contained in:
parent
74f6e1ab69
commit
8e075dd904
@ -360,8 +360,7 @@ function App() {
|
|||||||
<Alert variant={'primary'}>
|
<Alert variant={'primary'}>
|
||||||
Poslední změny:
|
Poslední změny:
|
||||||
<ul>
|
<ul>
|
||||||
<li>Oprava parsování restaurace U Motlíků, pokud neexistuje nabídka pro první den v týdnu</li>
|
<li>Základní pizza kalkulačka (v menu)</li>
|
||||||
<li>Oprava parsování restaurace Sladovnická, pokud nabídka nezačíná pondělím</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</Alert>
|
</Alert>
|
||||||
{dayIndex != null &&
|
{dayIndex != null &&
|
||||||
|
@ -7,6 +7,7 @@ import FeaturesVotingModal from "./modals/FeaturesVotingModal";
|
|||||||
import { FeatureRequest } from "../types";
|
import { FeatureRequest } from "../types";
|
||||||
import { errorHandler } from "../api/Api";
|
import { errorHandler } from "../api/Api";
|
||||||
import { getFeatureVotes, updateFeatureVote } from "../api/VotingApi";
|
import { getFeatureVotes, updateFeatureVote } from "../api/VotingApi";
|
||||||
|
import PizzaCalculatorModal from "./modals/PizzaCalculatorModal";
|
||||||
|
|
||||||
|
|
||||||
export default function Header() {
|
export default function Header() {
|
||||||
@ -14,6 +15,7 @@ export default function Header() {
|
|||||||
const bank = useBank();
|
const bank = useBank();
|
||||||
const [bankModalOpen, setBankModalOpen] = useState<boolean>(false);
|
const [bankModalOpen, setBankModalOpen] = useState<boolean>(false);
|
||||||
const [votingModalOpen, setVotingModalOpen] = useState<boolean>(false);
|
const [votingModalOpen, setVotingModalOpen] = useState<boolean>(false);
|
||||||
|
const [pizzaModalOpen, setPizzaModalOpen] = useState<boolean>(false);
|
||||||
const [featureVotes, setFeatureVotes] = useState<FeatureRequest[]>([]);
|
const [featureVotes, setFeatureVotes] = useState<FeatureRequest[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -32,6 +34,10 @@ export default function Header() {
|
|||||||
setVotingModalOpen(false);
|
setVotingModalOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const closePizzaModal = () => {
|
||||||
|
setPizzaModalOpen(false);
|
||||||
|
}
|
||||||
|
|
||||||
const isValidInteger = (str: string) => {
|
const isValidInteger = (str: string) => {
|
||||||
str = str.trim();
|
str = str.trim();
|
||||||
if (!str) {
|
if (!str) {
|
||||||
@ -108,11 +114,14 @@ export default function Header() {
|
|||||||
<NavDropdown align="end" title={auth?.login} id="basic-nav-dropdown">
|
<NavDropdown align="end" title={auth?.login} id="basic-nav-dropdown">
|
||||||
<NavDropdown.Item onClick={() => setBankModalOpen(true)}>Nastavit číslo účtu</NavDropdown.Item>
|
<NavDropdown.Item onClick={() => setBankModalOpen(true)}>Nastavit číslo účtu</NavDropdown.Item>
|
||||||
<NavDropdown.Item onClick={() => setVotingModalOpen(true)}>Hlasovat o nových funkcích</NavDropdown.Item>
|
<NavDropdown.Item onClick={() => setVotingModalOpen(true)}>Hlasovat o nových funkcích</NavDropdown.Item>
|
||||||
|
<NavDropdown.Item onClick={() => setPizzaModalOpen(true)}>Pizza kalkulačka</NavDropdown.Item>
|
||||||
|
<NavDropdown.Divider />
|
||||||
<NavDropdown.Item onClick={auth?.logout}>Odhlásit se</NavDropdown.Item>
|
<NavDropdown.Item onClick={auth?.logout}>Odhlásit se</NavDropdown.Item>
|
||||||
</NavDropdown>
|
</NavDropdown>
|
||||||
</Nav>
|
</Nav>
|
||||||
</Navbar.Collapse>
|
</Navbar.Collapse>
|
||||||
<BankAccountModal isOpen={bankModalOpen} onClose={closeBankModal} onSave={saveBankAccount} />
|
<BankAccountModal isOpen={bankModalOpen} onClose={closeBankModal} onSave={saveBankAccount} />
|
||||||
<FeaturesVotingModal isOpen={votingModalOpen} onClose={closeVotingModal} onChange={saveFeatureVote} initialValues={featureVotes} />
|
<FeaturesVotingModal isOpen={votingModalOpen} onClose={closeVotingModal} onChange={saveFeatureVote} initialValues={featureVotes} />
|
||||||
|
<PizzaCalculatorModal isOpen={pizzaModalOpen} onClose={closePizzaModal} />
|
||||||
</Navbar>
|
</Navbar>
|
||||||
}
|
}
|
141
client/src/components/modals/PizzaCalculatorModal.tsx
Normal file
141
client/src/components/modals/PizzaCalculatorModal.tsx
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import { useRef, useState } from "react";
|
||||||
|
import { Modal, Button, Row, Col } from "react-bootstrap"
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isOpen: boolean,
|
||||||
|
onClose: () => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Result = {
|
||||||
|
pizza1?: {
|
||||||
|
diameter?: number,
|
||||||
|
area?: number,
|
||||||
|
pricePerM?: number,
|
||||||
|
},
|
||||||
|
pizza2?: {
|
||||||
|
diameter?: number,
|
||||||
|
area?: number,
|
||||||
|
pricePerM?: number,
|
||||||
|
}
|
||||||
|
choice?: number,
|
||||||
|
ratio?: number,
|
||||||
|
diameterDiff?: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Modální dialog pro výpočet výhodnosti pizzy. */
|
||||||
|
export default function PizzaCalculatorModal({ isOpen, onClose }: Props) {
|
||||||
|
const diameter1Ref = useRef<HTMLInputElement>(null);
|
||||||
|
const price1Ref = useRef<HTMLInputElement>(null);
|
||||||
|
const diameter2Ref = useRef<HTMLInputElement>(null);
|
||||||
|
const price2Ref = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
const [result, setResult] = useState<Result | null>(null);
|
||||||
|
|
||||||
|
const recalculate = () => {
|
||||||
|
const r: Result = { ...result }
|
||||||
|
|
||||||
|
// 1. pizza
|
||||||
|
if (diameter1Ref.current?.value) {
|
||||||
|
const diameter1 = parseInt(diameter1Ref.current?.value);
|
||||||
|
if (!r.pizza1) {
|
||||||
|
r.pizza1 = {};
|
||||||
|
}
|
||||||
|
if (diameter1 && diameter1 > 0) {
|
||||||
|
r.pizza1.diameter = diameter1;
|
||||||
|
r.pizza1.area = Math.PI * Math.pow(diameter1 / 2, 2);
|
||||||
|
if (price1Ref.current?.value) {
|
||||||
|
const price1 = parseInt(price1Ref.current?.value);
|
||||||
|
if (price1) {
|
||||||
|
r.pizza1.pricePerM = price1 / r.pizza1.area;
|
||||||
|
} else {
|
||||||
|
r.pizza1.pricePerM = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r.pizza1.area = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. pizza
|
||||||
|
if (diameter2Ref.current?.value) {
|
||||||
|
const diameter2 = parseInt(diameter2Ref.current?.value);
|
||||||
|
if (!r.pizza2) {
|
||||||
|
r.pizza2 = {};
|
||||||
|
}
|
||||||
|
if (diameter2 && diameter2 > 0) {
|
||||||
|
r.pizza2.diameter = diameter2;
|
||||||
|
r.pizza2.area = Math.PI * Math.pow(diameter2 / 2, 2);
|
||||||
|
if (price2Ref.current?.value) {
|
||||||
|
const price2 = parseInt(price2Ref.current?.value);
|
||||||
|
if (price2) {
|
||||||
|
r.pizza2.pricePerM = price2 / r.pizza2.area;
|
||||||
|
} else {
|
||||||
|
r.pizza2.pricePerM = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r.pizza2.area = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Srovnání
|
||||||
|
if (r.pizza1?.pricePerM && r.pizza2?.pricePerM && r.pizza1.diameter && r.pizza2.diameter) {
|
||||||
|
r.choice = r.pizza1.pricePerM < r.pizza2.pricePerM ? 1 : 2;
|
||||||
|
const bigger = r.pizza1.pricePerM > r.pizza2.pricePerM ? r.pizza1.pricePerM : r.pizza2.pricePerM;
|
||||||
|
const smaller = r.pizza1.pricePerM < r.pizza2.pricePerM ? r.pizza1.pricePerM : r.pizza2.pricePerM;
|
||||||
|
r.ratio = (bigger / smaller) - 1;
|
||||||
|
r.diameterDiff = Math.abs(r.pizza1.diameter - r.pizza2.diameter);
|
||||||
|
} else {
|
||||||
|
r.choice = undefined;
|
||||||
|
r.ratio = undefined;
|
||||||
|
r.diameterDiff = undefined;
|
||||||
|
}
|
||||||
|
setResult(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
setResult(null);
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Modal show={isOpen} onHide={onClose}>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>Pizza kalkulačka</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<p>Zadejte parametry pizzy pro jejich srovnání.</p>
|
||||||
|
<Row>
|
||||||
|
<Col size="6">
|
||||||
|
<input className="mb-3" ref={diameter1Ref} type="number" step="1" min="1" placeholder="Průměr 1. pizzy (cm)" onChange={recalculate} />
|
||||||
|
</Col>
|
||||||
|
<Col size="6">
|
||||||
|
<input className="mb-3" ref={diameter2Ref} type="number" step="1" min="1" placeholder="Průměr 2. pizzy (cm)" onChange={recalculate} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col size="6">
|
||||||
|
<input className="mb-3" ref={price1Ref} type="number" min="1" placeholder="Cena 1. pizzy (Kč)" onChange={recalculate} />
|
||||||
|
</Col>
|
||||||
|
<Col size="6">
|
||||||
|
<input className="mb-3" ref={price2Ref} type="number" min="1" placeholder="Cena 2. pizzy (Kč)" onChange={recalculate} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col size="6">
|
||||||
|
{result?.pizza1?.area && <p>Plocha: <b>{Math.round(result.pizza1.area * 10) / 10}</b> cm²</p>}
|
||||||
|
{result?.pizza1?.pricePerM && <p>Cena za m²: <b>{Math.round(result.pizza1.pricePerM * 1000000) / 100}</b> Kč</p>}
|
||||||
|
</Col>
|
||||||
|
<Col size="6">
|
||||||
|
{result?.pizza2?.area && <p>Plocha: <b>{Math.round(result.pizza2.area * 10) / 10}</b> cm²</p>}
|
||||||
|
{result?.pizza2?.pricePerM && <p>Cena za m²: <b>{Math.round(result.pizza2.pricePerM * 1000000) / 100}</b> Kč</p>}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
{result?.choice && result?.ratio && result?.ratio > 0 && result?.diameterDiff != null && <p><b>{result.choice}. pizza</b> je zhruba o <b>{Math.round(result.ratio * 1000) / 10}%</b> výhodnější než {result.choice === 1 ? "2" : "1"}. pizza.</p> || ''}
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<Button variant="primary" onClick={close}>
|
||||||
|
Zavřít
|
||||||
|
</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user