Commit fa7f194c authored by Djordje's avatar Djordje

Add protected route, qr code on payment order, fix missing translations and eslint warnings

parent daccff3f
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-i18next": "^11.18.4", "react-i18next": "^11.18.4",
"react-qr-code": "^2.0.8",
"react-router-dom": "^6.3.0", "react-router-dom": "^6.3.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"tweetnacl": "^1.0.3", "tweetnacl": "^1.0.3",
...@@ -14049,6 +14050,11 @@ ...@@ -14049,6 +14050,11 @@
"teleport": ">=0.2.0" "teleport": ">=0.2.0"
} }
}, },
"node_modules/qr.js": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz",
"integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ=="
},
"node_modules/qs": { "node_modules/qs": {
"version": "6.10.3", "version": "6.10.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
...@@ -14337,6 +14343,24 @@ ...@@ -14337,6 +14343,24 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
}, },
"node_modules/react-qr-code": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.8.tgz",
"integrity": "sha512-zYO9EAPQU8IIeD6c6uAle7NlKOiVKs8ji9hpbWPTGxO+FLqBN2on+XCXQvnhm91nrRd306RvNXUkUNcXXSfhWA==",
"dependencies": {
"prop-types": "^15.8.1",
"qr.js": "0.0.0"
},
"peerDependencies": {
"react": "^16.x || ^17.x || ^18.x",
"react-native-svg": "*"
},
"peerDependenciesMeta": {
"react-native-svg": {
"optional": true
}
}
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
...@@ -26990,6 +27014,11 @@ ...@@ -26990,6 +27014,11 @@
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
"integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw=="
}, },
"qr.js": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz",
"integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ=="
},
"qs": { "qs": {
"version": "6.10.3", "version": "6.10.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
...@@ -27190,6 +27219,15 @@ ...@@ -27190,6 +27219,15 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
}, },
"react-qr-code": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.8.tgz",
"integrity": "sha512-zYO9EAPQU8IIeD6c6uAle7NlKOiVKs8ji9hpbWPTGxO+FLqBN2on+XCXQvnhm91nrRd306RvNXUkUNcXXSfhWA==",
"requires": {
"prop-types": "^15.8.1",
"qr.js": "0.0.0"
}
},
"react-refresh": { "react-refresh": {
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-i18next": "^11.18.4", "react-i18next": "^11.18.4",
"react-qr-code": "^2.0.8",
"react-router-dom": "^6.3.0", "react-router-dom": "^6.3.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"tweetnacl": "^1.0.3", "tweetnacl": "^1.0.3",
......
import React from 'react';
import './App.css'; import './App.css';
import { BrowserRouter as Router, Navigate, Route, Routes } from 'react-router-dom' import { BrowserRouter as Router, Navigate, Route, Routes } from 'react-router-dom'
import { EntryPage } from './components/entry-page/EntryPage'; import { EntryPage } from './components/entry-page/EntryPage';
...@@ -6,6 +5,7 @@ import { RegisterForm } from './components/register/RegisterForm'; ...@@ -6,6 +5,7 @@ import { RegisterForm } from './components/register/RegisterForm';
import { LoginForm } from './components/LoginForm'; import { LoginForm } from './components/LoginForm';
import { Application } from './components/Application'; import { Application } from './components/Application';
import { createTheme, ThemeProvider } from '@mui/material'; import { createTheme, ThemeProvider } from '@mui/material';
import { ProtectedRoute } from './components/ProtectedRoute';
const theme = createTheme({ const theme = createTheme({
palette: { palette: {
...@@ -19,7 +19,7 @@ const theme = createTheme({ ...@@ -19,7 +19,7 @@ const theme = createTheme({
fontSize: '1rem', fontSize: '1rem',
}, },
allVariants: { allVariants: {
color: 'rgb(39, 49, 58)' color: 'rgb(39, 49, 58)'
} }
}, },
}); });
...@@ -33,7 +33,7 @@ function App() { ...@@ -33,7 +33,7 @@ function App() {
<Route path='register/:buildingId' element={<EntryPage children={<RegisterForm />} />} /> <Route path='register/:buildingId' element={<EntryPage children={<RegisterForm />} />} />
<Route path='register/error' element={<EntryPage children={<div>Invalid invitational link - screen to be implemented</div>} />} /> <Route path='register/error' element={<EntryPage children={<div>Invalid invitational link - screen to be implemented</div>} />} />
<Route path='login' element={<EntryPage children={<LoginForm />} />} /> <Route path='login' element={<EntryPage children={<LoginForm />} />} />
<Route path='tenant/*' element={<Application />} /> <Route path='tenant/*' element={<ProtectedRoute><Application /></ProtectedRoute>} />
<Route path='*' element={<Navigate replace to="login" />} /> <Route path='*' element={<Navigate replace to="login" />} />
</Routes> </Routes>
</Router> </Router>
......
import { fetchRequestManager, fetchRequestTenant } from './network-manager' import { fetchRequestManager, fetchRequestTenant } from './network-manager'
import { fetchBuildingsSuccess, genericAction, TENANT_BUILDING_RECEIVED, UNAUTHENTICATED, TENANT_VOTING_RECEIVED } from './index' import { fetchBuildingsSuccess, genericAction, UNAUTHENTICATED } from './index'
export function fetchBuildings() { export function fetchBuildings() {
......
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import jwtDecode from "jwt-decode"; import jwtDecode from "jwt-decode";
import { useEffect, useRef, useState } from "react" import React from "react";
import { useNavigate } from "react-router-dom" import { useEffect, useState } from "react"
import { getBuilding, getTenantInfo } from "../actions/data-manager"; import { getBuilding, getTenantInfo } from "../actions/data-manager";
import { JWT_TENANT } from "../actions/network-manager" import { JWT_TENANT } from "../actions/network-manager"
import { ApplicationTab } from "./ApplicationTab"; import { ApplicationTab } from "./ApplicationTab";
...@@ -25,10 +25,10 @@ export const getBuildingId = () => { ...@@ -25,10 +25,10 @@ export const getBuildingId = () => {
return res.bl[0].id; return res.bl[0].id;
} }
export const ApplicationContext = React.createContext<any>(null);
export const Application = () => { export const Application = () => {
const navigate = useRef(useNavigate());
const [logedIn, setLogedIn] = useState(false);
const [sideMenuOpen, setSideMenuOpen] = useState(false); const [sideMenuOpen, setSideMenuOpen] = useState(false);
const [tenantInfo, setTenantInfo] = useState<any>(); const [tenantInfo, setTenantInfo] = useState<any>();
const [selectedUnit, setSelectedUnit] = useState<any>(''); const [selectedUnit, setSelectedUnit] = useState<any>('');
...@@ -44,15 +44,9 @@ export const Application = () => { ...@@ -44,15 +44,9 @@ export const Application = () => {
}; };
useEffect(() => { useEffect(() => {
if (!!localStorage.getItem(JWT_TENANT)) { getBuilding(buildingId, (err: any, data: any) => {
getBuilding(buildingId, (err: any, data: any) => { setBuilding(data);
setBuilding(data); });
});
return;
}
navigate.current('../login');
}, [buildingId]); }, [buildingId]);
useEffect(() => { useEffect(() => {
...@@ -60,13 +54,12 @@ export const Application = () => { ...@@ -60,13 +54,12 @@ export const Application = () => {
getTenantInfo((err: any, data: any) => { getTenantInfo((err: any, data: any) => {
setTenantInfo(data); setTenantInfo(data);
setSelectedUnit(building.units.filter((unit: any) => unit._id === data.buildings[0].units[0])[0] || ''); setSelectedUnit(building.units.filter((unit: any) => unit._id === data.buildings[0].units[0])[0] || '');
setLogedIn(true);
}); });
}, [building]); }, [building]);
return ( return (
<> <ApplicationContext.Provider value={{ tenantInfo }}>
{logedIn && building && {!!building && !!tenantInfo &&
<Box sx={classes.mainWrapper}> <Box sx={classes.mainWrapper}>
<SideMenu active={sideMenuOpen} toggleSideMenu={toggleSideMenu} email={tenantInfo.email} firstName={tenantInfo.firstName} /> <SideMenu active={sideMenuOpen} toggleSideMenu={toggleSideMenu} email={tenantInfo.email} firstName={tenantInfo.firstName} />
<Box sx={classes.rightSideWrapper}> <Box sx={classes.rightSideWrapper}>
...@@ -75,6 +68,6 @@ export const Application = () => { ...@@ -75,6 +68,6 @@ export const Application = () => {
</Box> </Box>
</Box> </Box>
} }
</> </ApplicationContext.Provider>
) )
} }
\ No newline at end of file
...@@ -4,7 +4,7 @@ import { BuildingInvoicesList } from "./BuildingInvoicesList"; ...@@ -4,7 +4,7 @@ import { BuildingInvoicesList } from "./BuildingInvoicesList";
export const BuildingInvoices = ({ buildingFinance }: { buildingFinance: any }) => { export const BuildingInvoices = ({ buildingFinance }: { buildingFinance: any }) => {
return ( return (
<TabWrapper header='Finansije Zgrade'> <TabWrapper header='Building finance'>
<BuildingInvoicesList buildingFinance={buildingFinance} /> <BuildingInvoicesList buildingFinance={buildingFinance} />
</TabWrapper> </TabWrapper>
); );
......
...@@ -43,15 +43,15 @@ export const BuildingInvoicesList = ({ buildingFinance }: { buildingFinance: any ...@@ -43,15 +43,15 @@ export const BuildingInvoicesList = ({ buildingFinance }: { buildingFinance: any
let finance = buildingFinance || {} let finance = buildingFinance || {}
let buildingPayable = buildingFinance && buildingFinance.payable && buildingFinance.payable.reduce((acc: any, x: any) => acc + x.price, 0) // let buildingPayable = buildingFinance && buildingFinance.payable && buildingFinance.payable.reduce((acc: any, x: any) => acc + x.price, 0)
let inflowSum = buildingFinance && buildingFinance.inflow && buildingFinance.inflow.reduce((acc: any, x: any) => acc + x.amount, 0) // let inflowSum = buildingFinance && buildingFinance.inflow && buildingFinance.inflow.reduce((acc: any, x: any) => acc + x.amount, 0)
let outflowSum = buildingFinance && buildingFinance.outflow && buildingFinance.outflow.reduce((acc: any, x: any) => acc + x.amount, 0) // let outflowSum = buildingFinance && buildingFinance.outflow && buildingFinance.outflow.reduce((acc: any, x: any) => acc + x.amount, 0)
let sumFundsPayables = (buildingFinance && buildingFinance.fund && buildingFinance.fund.reduce((acc: any, x: any) => acc + (x.receivable || 0), 0) || 0) // let sumFundsPayables = (buildingFinance && buildingFinance.fund && buildingFinance.fund.reduce((acc: any, x: any) => acc + (x.receivable || 0), 0) || 0)
let fullBalance = buildingFinance && inflowSum && buildingPayable && (inflowSum - buildingPayable - sumFundsPayables) // let fullBalance = buildingFinance && inflowSum && buildingPayable && (inflowSum - buildingPayable - sumFundsPayables)
let cashBalance = buildingFinance && buildingFinance.balance // let cashBalance = buildingFinance && buildingFinance.balance
let calculatedCashBalance = buildingFinance && (inflowSum - outflowSum) // let calculatedCashBalance = buildingFinance && (inflowSum - outflowSum)
let outflows = buildingFinance ? buildingFinance.outflow : [] let outflows = buildingFinance ? buildingFinance.outflow : []
......
...@@ -14,7 +14,7 @@ export const Issues = ({ issues }: { issues: any }) => { ...@@ -14,7 +14,7 @@ export const Issues = ({ issues }: { issues: any }) => {
<Issue issue={issue} key={index} /> <Issue issue={issue} key={index} />
)) ))
} }
{issues.length === 0 && <Typography>{t("Trenutno nema aktivnosti za ovu jedinicu")}.</Typography>} {issues.length === 0 && <Typography>{t("Currently there are not notifications for this unit")}.</Typography>}
</TabWrapper> </TabWrapper>
); );
} }
\ No newline at end of file
...@@ -15,7 +15,7 @@ export const UnitSelect = ({ units, selectedUnit, onUnitChange }: { units: any[] ...@@ -15,7 +15,7 @@ export const UnitSelect = ({ units, selectedUnit, onUnitChange }: { units: any[]
<Select <Select
size="small" size="small"
variant='standard' variant='standard'
value={selectedUnit._id} value={(!!selectedUnit && selectedUnit._id) || ''}
label="Age" label="Age"
onChange={(e) => { if (!!onUnitChange) onUnitChange(e.target.value) }} onChange={(e) => { if (!!onUnitChange) onUnitChange(e.target.value) }}
startAdornment={<InputAdornment position="start"> startAdornment={<InputAdornment position="start">
......
import { ReactNode } from "react";
import { Navigate, useLocation } from "react-router";
import { JWT_TENANT } from "../actions/network-manager";
export const ProtectedRoute = ({ children }: { children: ReactNode }): JSX.Element => {
const location = useLocation();
const isAuthenticated = !!localStorage.getItem(JWT_TENANT);
if (isAuthenticated) {
return <>{children}</>
} else {
return <Navigate to={{ pathname: '/app/login' }} state={{ from: location }} replace />;
}
}
\ No newline at end of file
import { Box, Divider, Typography } from "@mui/material"; import { Box, Divider, Typography } from "@mui/material";
import { useContext } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import QRCode from "react-qr-code";
import { ApplicationContext } from "../Application";
import { Card } from "../Card/Card"; import { Card } from "../Card/Card";
import { PaymentOrderItem } from "./PaymentOrderItem"; import { PaymentOrderItem } from "./PaymentOrderItem";
...@@ -9,7 +12,7 @@ const classes = { ...@@ -9,7 +12,7 @@ const classes = {
}, },
mainContainer: { mainContainer: {
display: 'flex', display: 'flex',
alignItems: 'center' alignItems: 'baseline'
}, },
itemsContainer: { itemsContainer: {
flex: 1, flex: 1,
...@@ -33,28 +36,40 @@ const classes = { ...@@ -33,28 +36,40 @@ const classes = {
export const PaymentOrder = ({ recipient, debit, bankAccount, payReference }: { recipient: string, debit: number, bankAccount: string, payReference: string }) => { export const PaymentOrder = ({ recipient, debit, bankAccount, payReference }: { recipient: string, debit: number, bankAccount: string, payReference: string }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { tenantInfo } = useContext(ApplicationContext);
const qrCode = `K:PR|V:01|C:1|R:${bankAccount}|N:${recipient}|I:RSD${(debit > 0 ? debit : 0).toFixed(2).toString().replace('.', ',')}` +
`|P:${tenantInfo.firstName} ${tenantInfo.lastName}|SF:289|S:Po nalogu gradjana|RO:00${payReference.replaceAll('-', '')}`;
return ( return (
<Card> <Card>
<Typography sx={classes.title}>Nalog za uplatu</Typography> <Typography sx={classes.title}>Nalog za uplatu</Typography>
<Box sx={classes.mainContainer}> <Box sx={classes.mainContainer}>
<Box sx={classes.itemsContainer}> <Box sx={classes.itemsContainer}>
<PaymentOrderItem flex={1} label="Uplatilac" size="large" /> <PaymentOrderItem flex={1} label="Uplatilac" size="large" value={`${tenantInfo.firstName} ${tenantInfo.lastName}`} />
<PaymentOrderItem flex={1} label="Svrha uplate" size="large" /> <PaymentOrderItem flex={1} label="Svrha uplate" size="large" />
<PaymentOrderItem flex={1} label="Primalac" size="large" value={recipient} /> <PaymentOrderItem flex={1} label="Primalac" size="large" value={recipient} />
</Box> </Box>
<Divider sx={classes.divider} orientation="vertical" variant="middle" flexItem /> <Divider sx={classes.divider} orientation="vertical" variant="middle" flexItem />
<Box sx={classes.itemsContainer}> <Box sx={classes.itemsContainer}>
<Box sx={classes.itemsGroup}> <Box sx={classes.itemsGroup}>
<PaymentOrderItem flex={1} label='sifra placanja' size="small" /> <PaymentOrderItem flex={1} label='sifra placanja' size="small" value='221' />
<PaymentOrderItem flex={1} label='valuta' size="small" value="RSD" /> <PaymentOrderItem flex={1} label='valuta' size="small" value="RSD" />
<PaymentOrderItem flex={4} label='iznos' size="small" value={t("nalog", { num: (debit > 0 ? debit : 0) })} /> <PaymentOrderItem flex={4} label='iznos' size="small" value={t("nalog", { num: (debit > 0 ? debit : 0) })} />
</Box> </Box>
<PaymentOrderItem flex={1} label='Racun primaonca' size="small" value={bankAccount} /> <PaymentOrderItem flex={1} label='Racun primaoca' size="small" value={bankAccount} />
<Box sx={classes.itemsGroup}> <Box sx={classes.itemsGroup}>
<PaymentOrderItem flex={1} label='model' size="small" /> <PaymentOrderItem flex={1} label='model' size="small" value='00' />
<PaymentOrderItem flex={4} label='poziv na broj' size="small" value={payReference} /> <PaymentOrderItem flex={4} label='poziv na broj' size="small" value={payReference.replaceAll('-', '')} />
</Box> </Box>
<div style={{ marginLeft: "auto", maxWidth: 80 }}>
<QRCode
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
value={qrCode}
viewBox={`0 0 256 256`}
/>
</div>
</Box> </Box>
</Box> </Box>
</Card> </Card>
......
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography } from "@mui/material"; import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography } from "@mui/material";
import { useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { PayableStatus } from "../BuildingInvoices/PayableStatus"; import { PayableStatus } from "../BuildingInvoices/PayableStatus";
import { Card } from "../Card/Card"; import { Card } from "../Card/Card";
...@@ -49,22 +49,22 @@ type Test = { ...@@ -49,22 +49,22 @@ type Test = {
export const TenantInvoices = ({ building, unit }: { building: any, unit: any }) => { export const TenantInvoices = ({ building, unit }: { building: any, unit: any }) => {
const getInfo = (): Test => { const getInfo = useCallback((): Test => {
let invoices = unit.invoices || []; let invoices = unit.invoices || [];
let bankAccount = (building.finance || {}).bankAccount; let bankAccount = (building.finance || {}).bankAccount;
let lastUnpaid = invoices.find((x: any) => x.status !== "paid") || {}; let lastUnpaid = invoices.find((x: any) => x.status !== "paid") || {};
let payReference = lastUnpaid.invoiceId || (invoices[invoices.length - 1] || {}).invoiceId; let payReference = lastUnpaid.invoiceId || (invoices[invoices.length - 1] || {}).invoiceId;
return { invoices, bankAccount, lastUnpaid, payReference }; return { invoices, bankAccount, lastUnpaid, payReference };
} }, [building.finance, unit.invoices]);
const { t } = useTranslation(); const { t, i18n } = useTranslation();
const [info, setInfo] = useState<Test>(getInfo()); const [info, setInfo] = useState<Test>(getInfo());
useEffect(() => { useEffect(() => {
setInfo(getInfo()); setInfo(getInfo());
}, [unit, building]); }, [unit, building, getInfo]);
return ( return (
<TabWrapper header="My Account"> <TabWrapper header="My Account">
...@@ -93,12 +93,13 @@ export const TenantInvoices = ({ building, unit }: { building: any, unit: any }) ...@@ -93,12 +93,13 @@ export const TenantInvoices = ({ building, unit }: { building: any, unit: any })
{info.invoices.length === 0 && <Typography sx={classes.noRecords} >{t('No records')}</Typography>} {info.invoices.length === 0 && <Typography sx={classes.noRecords} >{t('No records')}</Typography>}
</TableContainer> </TableContainer>
</Card> </Card>
{i18n.language === 'sr' &&
<PaymentOrder <PaymentOrder
recipient={building.name} recipient={building.name}
debit={unit.debit} debit={unit.debit}
bankAccount={info.bankAccount} bankAccount={info.bankAccount}
payReference={info.payReference} /> payReference={info.payReference} />
}
</TabWrapper> </TabWrapper>
); );
} }
\ No newline at end of file
...@@ -40,7 +40,7 @@ export const Voting = (): JSX.Element => { ...@@ -40,7 +40,7 @@ export const Voting = (): JSX.Element => {
const [voting, setVoting] = useState<VotingEntity>(); const [voting, setVoting] = useState<VotingEntity>();
const [selectedCandidateId, setSelectedCandidateId] = useState(''); const [selectedCandidateId, setSelectedCandidateId] = useState('');
const [errorText, setErrorText] = useState(''); const [errorText, setErrorText] = useState('');
const [privateKey, setPrivateKey] = useState(localStorage.getItem(PRIVATE_KEY)); const [privateKey] = useState(localStorage.getItem(PRIVATE_KEY));
const { t } = useTranslation(); const { t } = useTranslation();
...@@ -97,6 +97,7 @@ export const Voting = (): JSX.Element => { ...@@ -97,6 +97,7 @@ export const Voting = (): JSX.Element => {
</RadioGroup> </RadioGroup>
</FormControl> </FormControl>
<Button variant='contained' sx={classes.button} disabled={selectedCandidateId === ''} onClick={handleVote}>{t("Vote")}</Button> <Button variant='contained' sx={classes.button} disabled={selectedCandidateId === ''} onClick={handleVote}>{t("Vote")}</Button>
{!!errorText && <Typography color='error'>{errorText}</Typography>}
</> </>
} }
{status === "voted" && <Typography>{t('Thank you for voting')}. </Typography>} {status === "voted" && <Typography>{t('Thank you for voting')}. </Typography>}
...@@ -105,7 +106,7 @@ export const Voting = (): JSX.Element => { ...@@ -105,7 +106,7 @@ export const Voting = (): JSX.Element => {
</> </>
} }
{ {
!privateKey && <Warning text={t("Voting is disabled because private key isn't saved in application. Please, set up key in settings")} /> !privateKey && <Warning text={"Voting is disabled because private key isn't saved in application. Please, set up key in settings"} />
} }
</TabWrapper> </TabWrapper>
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment