Možnost hlasování o nových funkcích

This commit is contained in:
2023-09-27 18:35:18 +02:00
parent 401833f763
commit 8e285e9197
7 changed files with 177 additions and 11 deletions

View File

@@ -1,5 +1,5 @@
import { toast } from "react-toastify";
import { PizzaOrder } from "./types";
import { FeatureRequest, PizzaOrder } from "./types";
import { getBaseUrl, getToken } from "./Utils";
/**
@@ -110,4 +110,12 @@ export const changeDepartureTime = async (time: string, dayIndex?: number) => {
export const updatePizzaFee = async (login: string, text?: string, price?: number) => {
return await api.post<any, any>('/api/updatePizzaFee', JSON.stringify({ login, text, price }));
}
export const getFeatureVotes = async () => {
return await api.get<any>('/api/getFeatureVotes');
}
export const updateFeatureVote = async (option: FeatureRequest, active: boolean) => {
return await api.post<any, any>('/api/updateFeatureVote', JSON.stringify({ option, active }));
}

View File

@@ -356,6 +356,7 @@ function App() {
<li>Možnost ručního zadání příplatku k Pizza day objednávkám</li>
<li>Vylepšená detekce uzavření pro podniky Sladovnická a TechTower</li>
<li>Úprava zvýraznění aktuálního dne</li>
<li>Možnost hlasování o nových funkcích</li>
</ul>
</Alert>
{dayIndex != null &&

View File

@@ -1,21 +1,34 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import { Navbar, Nav, NavDropdown } from "react-bootstrap";
import { useAuth } from "../context/auth";
import BankAccountModal from "./modals/BankAccountModal";
import { useBank } from "../context/bank";
import FeaturesVotingModal from "./modals/FeaturesVotingModal";
import { FeatureRequest } from "../types";
import { errorHandler, getFeatureVotes, updateFeatureVote } from "../Api";
export default function Header() {
const auth = useAuth();
const bank = useBank();
const [modalOpen, setModalOpen] = useState<boolean>(false);
const [bankModalOpen, setBankModalOpen] = useState<boolean>(false);
const [votingModalOpen, setVotingModalOpen] = useState<boolean>(false);
const [featureVotes, setFeatureVotes] = useState<FeatureRequest[]>([]);
const openBankSettings = () => {
setModalOpen(true);
useEffect(() => {
if (auth?.login) {
getFeatureVotes().then(votes => {
setFeatureVotes(votes);
})
}
}, [auth?.login]);
const closeBankModal = () => {
setBankModalOpen(false);
}
const closeModal = () => {
setModalOpen(false);
const closeVotingModal = () => {
setVotingModalOpen(false);
}
const isValidInteger = (str: string) => {
@@ -28,7 +41,7 @@ export default function Header() {
return n !== Infinity && String(n) === str && n >= 0;
}
const save = (bankAccountNumber?: string, bankAccountHolderName?: string) => {
const saveBankAccount = (bankAccountNumber?: string, bankAccountHolderName?: string) => {
if (bankAccountNumber) {
try {
// Validace kódu banky
@@ -72,7 +85,18 @@ export default function Header() {
}
bank?.setBankAccountNumber(bankAccountNumber);
bank?.setBankAccountHolderName(bankAccountHolderName);
closeModal();
closeBankModal();
}
const saveFeatureVote = async (option: FeatureRequest, active: boolean) => {
await errorHandler(() => updateFeatureVote(option, active));
const votes = [...featureVotes];
if (active) {
votes.push(option);
} else {
votes.splice(votes.indexOf(option), 1);
}
setFeatureVotes(votes);
}
return <Navbar variant='dark' expand="lg">
@@ -81,11 +105,13 @@ export default function Header() {
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="nav">
<NavDropdown align="end" title={auth?.login} id="basic-nav-dropdown">
<NavDropdown.Item onClick={openBankSettings}>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={auth?.logout}>Odhlásit se</NavDropdown.Item>
</NavDropdown>
</Nav>
</Navbar.Collapse>
<BankAccountModal isOpen={modalOpen} onClose={closeModal} onSave={save} />
<BankAccountModal isOpen={bankModalOpen} onClose={closeBankModal} onSave={saveBankAccount} />
<FeaturesVotingModal isOpen={votingModalOpen} onClose={closeVotingModal} onChange={saveFeatureVote} initialValues={featureVotes} />
</Navbar>
}

View File

@@ -0,0 +1,45 @@
import { Modal, Button, Form } from "react-bootstrap"
import { FeatureRequest } from "../../types";
type Props = {
isOpen: boolean,
onClose: () => void,
onChange: (option: FeatureRequest, active: boolean) => void,
initialValues?: FeatureRequest[],
}
/** Modální dialog pro hlasování o nových funkcích. */
export default function FeaturesVotingModal({ isOpen, onClose, onChange, initialValues }: Props) {
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
onChange(e.currentTarget.value as FeatureRequest, e.currentTarget.checked);
}
return <Modal show={isOpen} onHide={onClose} size="lg">
<Modal.Header closeButton>
<Modal.Title>
Hlasujte pro nové funkce
<p style={{ fontSize: '12px' }}>Je možno vybrat maximálně 3 možnosti</p>
</Modal.Title>
</Modal.Header>
<Modal.Body>
{(Object.keys(FeatureRequest) as Array<keyof typeof FeatureRequest>).map(key => {
return <Form.Check
key={key}
type='checkbox'
id={key}
label={FeatureRequest[key]}
onChange={handleChange}
value={key}
defaultChecked={initialValues && initialValues.includes(key as FeatureRequest)}
/>
})}
<p className="mt-3" style={{ fontSize: '12px' }}>Něco jiného? Dejte vědět.</p>
</Modal.Body>
<Modal.Footer>
<Button variant="primary" onClick={onClose}>
Zavřít
</Button>
</Modal.Footer>
</Modal>
}