Commit daccff3f authored by Djordje's avatar Djordje

Add translations

parent 893f496e
...@@ -31,7 +31,7 @@ export const Application = () => { ...@@ -31,7 +31,7 @@ export const Application = () => {
const [logedIn, setLogedIn] = useState(false); 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>('');
const [buildingId] = useState(getBuildingId()); const [buildingId] = useState(getBuildingId());
const [building, setBuilding] = useState<any>(); const [building, setBuilding] = useState<any>();
...@@ -59,7 +59,7 @@ export const Application = () => { ...@@ -59,7 +59,7 @@ export const Application = () => {
if (!!building) if (!!building)
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); setLogedIn(true);
}); });
}, [building]); }, [building]);
......
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material"; import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography } from "@mui/material";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Card } from "../Card/Card"; import { Card } from "../Card/Card";
import { PayableStatus } from "./PayableStatus"; import { PayableStatus } from "./PayableStatus";
const classes = { const classes = {
tableContainer: {
minHeight: '150px',
position: 'relative'
},
tableHead: { tableHead: {
'& .MuiTableCell-root': { '& .MuiTableCell-root': {
color: '#64748b', color: '#64748b',
...@@ -24,6 +28,11 @@ const classes = { ...@@ -24,6 +28,11 @@ const classes = {
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center' alignItems: 'center'
},
noRecords: {
position: 'absolute',
top: `60%`,
left: '45%'
} }
} as const; } as const;
...@@ -58,7 +67,7 @@ export const BuildingInvoicesList = ({ buildingFinance }: { buildingFinance: any ...@@ -58,7 +67,7 @@ export const BuildingInvoicesList = ({ buildingFinance }: { buildingFinance: any
return ( return (
<Card> <Card>
<TableContainer > <TableContainer sx={classes.tableContainer}>
<Table size="medium"> <Table size="medium">
<TableHead> <TableHead>
<TableRow sx={classes.tableHead}> <TableRow sx={classes.tableHead}>
...@@ -81,6 +90,7 @@ export const BuildingInvoicesList = ({ buildingFinance }: { buildingFinance: any ...@@ -81,6 +90,7 @@ export const BuildingInvoicesList = ({ buildingFinance }: { buildingFinance: any
))} ))}
</TableBody> </TableBody>
</Table> </Table>
{payables.length === 0 && <Typography sx={classes.noRecords} >{t('No records')}</Typography>}
</TableContainer> </TableContainer>
</Card> </Card>
); );
......
...@@ -4,7 +4,7 @@ import { DocumentsList } from "./DocumentsList"; ...@@ -4,7 +4,7 @@ import { DocumentsList } from "./DocumentsList";
export const Documents = ({ documents }: { documents: any }) => { export const Documents = ({ documents }: { documents: any }) => {
return ( return (
<TabWrapper header="Dokumenta"> <TabWrapper header="Documents">
<DocumentsList documents={documents} /> <DocumentsList documents={documents} />
</TabWrapper> </TabWrapper>
); );
......
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material"; import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography } from "@mui/material";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Card } from "../Card/Card"; import { Card } from "../Card/Card";
import { DownloadIcon } from "../icons/DownloadIcon"; import { DownloadIcon } from "../icons/DownloadIcon";
import { LinkIcon } from "../icons/LinkIcon"; import { LinkIcon } from "../icons/LinkIcon";
const classes = { const classes = {
tableContainer: {
minHeight: '150px',
position: 'relative'
},
tableHead: { tableHead: {
'& .MuiTableCell-root': { '& .MuiTableCell-root': {
color: '#64748b', color: '#64748b',
...@@ -25,6 +29,11 @@ const classes = { ...@@ -25,6 +29,11 @@ const classes = {
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center' alignItems: 'center'
},
noRecords: {
position: 'absolute',
top: `60%`,
left: '45%'
} }
} as const; } as const;
...@@ -35,7 +44,7 @@ export const DocumentsList = ({ documents }: { documents: any }) => { ...@@ -35,7 +44,7 @@ export const DocumentsList = ({ documents }: { documents: any }) => {
return ( return (
<Card> <Card>
<TableContainer > <TableContainer sx={classes.tableContainer}>
<Table size="medium"> <Table size="medium">
<TableHead> <TableHead>
<TableRow sx={classes.tableHead}> <TableRow sx={classes.tableHead}>
...@@ -54,6 +63,7 @@ export const DocumentsList = ({ documents }: { documents: any }) => { ...@@ -54,6 +63,7 @@ export const DocumentsList = ({ documents }: { documents: any }) => {
))} ))}
</TableBody> </TableBody>
</Table> </Table>
{documents.length === 0 && <Typography sx={classes.noRecords} >{t('No documents')}</Typography>}
</TableContainer> </TableContainer>
</Card> </Card>
); );
......
import { Box, Collapse, Divider, Typography } from "@mui/material"; import { Box, Collapse, Divider, Typography } from "@mui/material";
import { display } from "@mui/system";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Card } from "../Card/Card"; import { Card } from "../Card/Card";
...@@ -44,21 +43,21 @@ export const Issue = ({ issue }: { issue: any }) => { ...@@ -44,21 +43,21 @@ export const Issue = ({ issue }: { issue: any }) => {
</Box> </Box>
</Box> </Box>
<Box sx={classes.description}> <Box sx={classes.description}>
<Typography sx={classes.subheader}>Opis</Typography> <Typography sx={classes.subheader}>{t("Description")}</Typography>
<Typography>{issue.description}</Typography> <Typography>{issue.description}</Typography>
</Box> </Box>
<Collapse in={expand} timeout={250}> <Collapse in={expand} timeout={250}>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '5px' }}> <Box sx={{ display: 'flex', flexDirection: 'column', gap: '5px' }}>
<Divider /> <Divider />
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '5px' }}> <Box sx={{ display: 'flex', flexDirection: 'column', gap: '5px' }}>
<Typography sx={classes.subheader}>Rešenja</Typography> <Typography sx={classes.subheader}>{t("Solutions")}</Typography>
{issue.solutions.map((solution: any, ind: number) => ( {issue.solutions.map((solution: any, ind: number) => (
<Box key={ind}> <Box key={ind}>
<Box sx={{ display: 'flex', flexDirection: 'row' }}> <Box sx={{ display: 'flex', flexDirection: 'row' }}>
<Typography >{`${ind + 1}. ${solution.name}`}</Typography> <Typography >{`${ind + 1}. ${solution.name}`}</Typography>
<Typography sx={{ marginLeft: 'auto', fontWeight: 'bold' }}>{`${t("priceFormat", { num: (solution.price) })}`}</Typography> <Typography sx={{ marginLeft: 'auto', fontWeight: 'bold' }}>{`${t("priceFormat", { num: (solution.price) })}`}</Typography>
</Box> </Box>
<Typography sx={{ paddingLeft: '10px', fontSize: '15px' }}>{solution.description || 'Opis resenja nije unet.'}</Typography> <Typography sx={{ paddingLeft: '10px', fontSize: '15px' }}>{solution.description || t('Description was not provided.')}</Typography>
</Box> </Box>
))} ))}
</Box> </Box>
......
import { Typography } from "@mui/material"; import { Typography } from "@mui/material";
import { useTranslation } from "react-i18next";
import { TabWrapper } from "../TabWrapper/TabWrapper"; import { TabWrapper } from "../TabWrapper/TabWrapper";
import { Issue } from "./Issue"; import { Issue } from "./Issue";
export const Issues = ({ issues }: { issues: any }) => { export const Issues = ({ issues }: { issues: any }) => {
const { t } = useTranslation();
return ( return (
<TabWrapper header="Aktivnosti"> <TabWrapper header="Issues">
{ {
issues.map((issue: any, index: number) => ( issues.map((issue: any, index: number) => (
<Issue issue={issue} key={index}/> <Issue issue={issue} key={index} />
)) ))
} }
{issues.length === 0 && <Typography>Trenutno nema aktivnosti za ovu jedinicu.</Typography>} {issues.length === 0 && <Typography>{t("Trenutno nema aktivnosti za ovu jedinicu")}.</Typography>}
</TabWrapper> </TabWrapper>
); );
} }
\ No newline at end of file
...@@ -29,11 +29,13 @@ const classes = { ...@@ -29,11 +29,13 @@ const classes = {
export const Notification = ({ title, description }: { title: string, description: string }) => { export const Notification = ({ title, description }: { title: string, description: string }) => {
const { t } = useTranslation();
return ( return (
<Card> <Card>
<Typography sx={classes.title}>{title}</Typography> <Typography sx={classes.title}>{title}</Typography>
<Box sx={classes.description}> <Box sx={classes.description}>
<Typography sx={classes.subheader}>Opis</Typography> <Typography sx={classes.subheader}>{t("Description")}</Typography>
<Typography>{description}</Typography> <Typography>{description}</Typography>
</Box> </Box>
</Card> </Card>
......
import { Typography } from "@mui/material"; import { Typography } from "@mui/material";
import { useTranslation } from "react-i18next";
import { TabWrapper } from "../TabWrapper/TabWrapper"; import { TabWrapper } from "../TabWrapper/TabWrapper";
import { Notification } from "./Notification"; import { Notification } from "./Notification";
export const Notifications = ({ notifications }: { notifications: any }) => { export const Notifications = ({ notifications }: { notifications: any }) => {
const { t } = useTranslation();
return ( return (
<TabWrapper header="Obaveštenja"> <TabWrapper header="Notifications">
{ {
notifications.map((notification: any, index: number) => ( notifications.map((notification: any, index: number) => (
<Notification title={notification.title} description={notification.description} /> <Notification title={notification.title} description={notification.description} />
)) ))
} }
{notifications.length === 0 && <Typography>Trenutno nema obavestenja za ovu jedinicu.</Typography>} {notifications.length === 0 && <Typography>{t("Currently there are not notifications for this unit")}.</Typography>}
</TabWrapper>); </TabWrapper>);
} }
\ No newline at end of file
...@@ -8,6 +8,7 @@ import { TabWrapper } from "../TabWrapper/TabWrapper"; ...@@ -8,6 +8,7 @@ import { TabWrapper } from "../TabWrapper/TabWrapper";
import { Buffer } from "buffer"; import { Buffer } from "buffer";
import nacl, { SignKeyPair } from "tweetnacl"; import nacl, { SignKeyPair } from "tweetnacl";
import { HelperIcon } from "../icons/HelperIcon"; import { HelperIcon } from "../icons/HelperIcon";
import { useTranslation } from "react-i18next";
const classes = { const classes = {
votingSeetings: { votingSeetings: {
...@@ -58,6 +59,7 @@ export const Settings = () => { ...@@ -58,6 +59,7 @@ export const Settings = () => {
const [toggleHelp, setToggleHelp] = useState(false); const [toggleHelp, setToggleHelp] = useState(false);
const helperRef = useRef<SVGSVGElement>(null); const helperRef = useRef<SVGSVGElement>(null);
const { t } = useTranslation();
useEffect(() => { useEffect(() => {
getTenantInfo((err: any, user: any) => { getTenantInfo((err: any, user: any) => {
...@@ -86,7 +88,7 @@ export const Settings = () => { ...@@ -86,7 +88,7 @@ export const Settings = () => {
setHelperText(''); setHelperText('');
} }
} catch (error) { } catch (error) {
setHelperText('Neispravan kljuc!'); setHelperText(t('Neispravan kljuc') + '!');
} }
} }
...@@ -107,7 +109,7 @@ export const Settings = () => { ...@@ -107,7 +109,7 @@ export const Settings = () => {
setPublicKey(publicKeyBase64); setPublicKey(publicKeyBase64);
} else { } else {
if (err.status === 412) { if (err.status === 412) {
alert("Not allowed already set key, contact your building manager") alert(t("Not allowed already set key, contact your building manager"))
} }
} }
})(null); })(null);
...@@ -125,17 +127,17 @@ export const Settings = () => { ...@@ -125,17 +127,17 @@ export const Settings = () => {
return ( return (
<TabWrapper header="Podešavanja" onClick={handleClickOutside}> <TabWrapper header="Settings" onClick={handleClickOutside}>
<Card> <Card>
{ {
!publicKey && !publicKey &&
<> <>
<Typography sx={classes.header}>Glasanje</Typography> <Typography sx={classes.header}>{t('Voting')}</Typography>
<Typography>Ukoliko zelite ucestvovati u glasanju potrebno je da generisete i sacuvate kljuceve u aplikaciji.</Typography> <Typography>{t("If you want to participate in voting you need to generate voting keys and save them in application")}</Typography>
{!!keyPair && {!!keyPair &&
<> <>
<Box> <Box>
<Typography>Privatni kljuc</Typography> <Typography>{t('Private key')}</Typography>
<TextField <TextField
variant="outlined" variant="outlined"
size='small' size='small'
...@@ -159,7 +161,7 @@ export const Settings = () => { ...@@ -159,7 +161,7 @@ export const Settings = () => {
{({ TransitionProps }) => ( {({ TransitionProps }) => (
<Fade {...TransitionProps} timeout={350}> <Fade {...TransitionProps} timeout={350}>
<Box sx={classes.helperCloud}> <Box sx={classes.helperCloud}>
<Typography sx={classes.helperText}>U slučaju da izgubite pristup ovom uređaju, ovaj ključ će vam biti potreban kako bi na novom uređaju mogli da učestvujete u glasanju!</Typography> <Typography sx={classes.helperText}>{t("In case you lose access to device, this key will be required to participate in voting")}!</Typography>
</Box> </Box>
</Fade> </Fade>
)} )}
...@@ -167,7 +169,18 @@ export const Settings = () => { ...@@ -167,7 +169,18 @@ export const Settings = () => {
</Box> </Box>
</> </>
} }
<Button variant='contained' sx={classes.button} onClick={() => { if (!keyPair) { generateKeys() } else { saveKeys(keyPair.publicKey, keyPair.secretKey) } }} disabled={!!keyPair && !privateKeyWritten}>{!keyPair ? 'Generisi' : 'Sacuvaj'}</Button> <Button
variant='contained'
sx={classes.button}
onClick={() => {
if (!keyPair) {
generateKeys()
}
else {
saveKeys(keyPair.publicKey, keyPair.secretKey)
}
}}
disabled={!!keyPair && !privateKeyWritten} >{!keyPair ? 'Generisi' : 'Sacuvaj'}</Button>
</> </>
} }
{!!publicKey && {!!publicKey &&
...@@ -175,8 +188,8 @@ export const Settings = () => { ...@@ -175,8 +188,8 @@ export const Settings = () => {
{!!privateKey && {!!privateKey &&
<Box sx={classes.votingSeetings}> <Box sx={classes.votingSeetings}>
<Box sx={classes.textWrapper}> <Box sx={classes.textWrapper}>
<Typography sx={classes.header}>Glasanje</Typography> <Typography sx={classes.header}>{t('Voting')}</Typography>
<Typography>Privatni ključ je uspešno podešen u aplikaciji.</Typography> <Typography>{t("Private key successfully set in application")}.</Typography>
</Box> </Box>
<CheckMark /> <CheckMark />
</Box> </Box>
...@@ -184,15 +197,15 @@ export const Settings = () => { ...@@ -184,15 +197,15 @@ export const Settings = () => {
{ {
!privateKey && !privateKey &&
<> <>
<Typography sx={classes.header}>Glasanje</Typography> <Typography sx={classes.header}>{t('Voting')}</Typography>
<Typography>Kako bi mogli da učestvujete u glasanju, molimo vas unesite vaš privatni ključ.</Typography> <Typography>{t("In order to participate in voting, please enter your private key")}.</Typography>
<TextField <TextField
error={!!helperText} error={!!helperText}
helperText={helperText} helperText={helperText}
onChange={(e) => { onChange={(e) => {
setNewPrivateKey(e.target.value); setNewPrivateKey(e.target.value);
}} size='small' /> }} size='small' />
<Button variant='contained' sx={classes.button} onClick={verifyKey}>Potvrdi</Button> <Button variant='contained' sx={classes.button} onClick={verifyKey}>{t('Confirm')}</Button>
</> </>
} }
</> </>
......
...@@ -16,7 +16,7 @@ export const subMenu: SubMenu[] = [ ...@@ -16,7 +16,7 @@ export const subMenu: SubMenu[] = [
items: [ items: [
{ title: 'Overview', icon: <HomeIcon />, path: 'overview' }, { title: 'Overview', icon: <HomeIcon />, path: 'overview' },
{ title: 'Notifications', icon: <NotificationIcon />, path: 'notifications' }, { title: 'Notifications', icon: <NotificationIcon />, path: 'notifications' },
{ title: 'Activities', icon: <ActivityIcon />, path: 'issues' }, { title: 'Issues', icon: <ActivityIcon />, path: 'issues' },
{ title: 'Voting', icon: <VotingIcon />, path: 'voting' } { title: 'Voting', icon: <VotingIcon />, path: 'voting' }
] ]
}, },
......
import { Box, Typography } from "@mui/material" import { Box, Typography } from "@mui/material"
import { ReactNode } from "react" import { ReactNode } from "react"
import { useTranslation } from "react-i18next";
import './TabWrapper.css' import './TabWrapper.css'
const classes = { const classes = {
...@@ -16,9 +17,12 @@ const classes = { ...@@ -16,9 +17,12 @@ const classes = {
} as const; } as const;
export const TabWrapper = ({ header, children, onClick }: { header: string, children?: ReactNode, onClick?: (e: any) => void }) => { export const TabWrapper = ({ header, children, onClick }: { header: string, children?: ReactNode, onClick?: (e: any) => void }) => {
const { t } = useTranslation();
return ( return (
<Box sx={classes.wrapper} onClick={(e) => { if (!!onClick) { onClick(e) } }}> <Box sx={classes.wrapper} onClick={(e) => { if (!!onClick) { onClick(e) } }}>
<Typography variant='h5' sx={classes.header}>{header}</Typography> <Typography variant='h5' sx={classes.header}>{t(header)}</Typography>
{children} {children}
</Box> </Box>
) )
......
...@@ -34,8 +34,8 @@ const classes = { ...@@ -34,8 +34,8 @@ const classes = {
}, },
noRecords: { noRecords: {
position: 'absolute', position: 'absolute',
top: `calc(50% - 10px)`, top: `60%`,
left: 'calc(50% - 30px)' left: '45%'
} }
} as const; } as const;
...@@ -67,7 +67,7 @@ export const TenantInvoices = ({ building, unit }: { building: any, unit: any }) ...@@ -67,7 +67,7 @@ export const TenantInvoices = ({ building, unit }: { building: any, unit: any })
}, [unit, building]); }, [unit, building]);
return ( return (
<TabWrapper header="Moj Račun"> <TabWrapper header="My Account">
<Card> <Card>
<TableContainer sx={classes.tableContainer}> <TableContainer sx={classes.tableContainer}>
<Table size="medium"> <Table size="medium">
...@@ -90,7 +90,7 @@ export const TenantInvoices = ({ building, unit }: { building: any, unit: any }) ...@@ -90,7 +90,7 @@ export const TenantInvoices = ({ building, unit }: { building: any, unit: any })
))} ))}
</TableBody> </TableBody>
</Table> </Table>
{info.invoices.length === 0 && <Typography sx={classes.noRecords} >No records</Typography>} {info.invoices.length === 0 && <Typography sx={classes.noRecords} >{t('No records')}</Typography>}
</TableContainer> </TableContainer>
</Card> </Card>
......
...@@ -9,6 +9,7 @@ import { Buffer } from "buffer"; ...@@ -9,6 +9,7 @@ import { Buffer } from "buffer";
import { TabWrapper } from "../TabWrapper/TabWrapper"; import { TabWrapper } from "../TabWrapper/TabWrapper";
import { Card } from "../Card/Card"; import { Card } from "../Card/Card";
import { getBuildingId } from "../Application"; import { getBuildingId } from "../Application";
import { useTranslation } from "react-i18next";
const classes = { const classes = {
wrapper: { wrapper: {
...@@ -41,6 +42,8 @@ export const Voting = (): JSX.Element => { ...@@ -41,6 +42,8 @@ export const Voting = (): JSX.Element => {
const [errorText, setErrorText] = useState(''); const [errorText, setErrorText] = useState('');
const [privateKey, setPrivateKey] = useState(localStorage.getItem(PRIVATE_KEY)); const [privateKey, setPrivateKey] = useState(localStorage.getItem(PRIVATE_KEY));
const { t } = useTranslation();
useEffect(() => { useEffect(() => {
getTenentVoting(getBuildingId(), (err: any, res: any, disp: any) => { getTenentVoting(getBuildingId(), (err: any, res: any, disp: any) => {
setStatus(res.status || "not allowed"); setStatus(res.status || "not allowed");
...@@ -62,7 +65,7 @@ export const Voting = (): JSX.Element => { ...@@ -62,7 +65,7 @@ export const Voting = (): JSX.Element => {
postVote(getBuildingId(), vote, (err: any, data: any) => { postVote(getBuildingId(), vote, (err: any, data: any) => {
if (err) { if (err) {
if (err.status === 406) { if (err.status === 406) {
setErrorText("Signature not valid!"); setErrorText(t("Signature not valid") + "!");
} else { } else {
setErrorText(err.errorMessage); setErrorText(err.errorMessage);
} }
...@@ -76,33 +79,33 @@ export const Voting = (): JSX.Element => { ...@@ -76,33 +79,33 @@ export const Voting = (): JSX.Element => {
return (<> return (<>
{ {
!!voting && !!voting &&
<TabWrapper header="Glasanje"> <TabWrapper header="Voting">
{!!privateKey && {!!privateKey &&
<> <>
{status === "not allowed" && <Warning text='Vaš nalog nije potvrđen kao vlasnik ni jedne jedinice. Molimo obratite se upravniku stambene zajednice.' />} {status === "not allowed" && <Warning text="You account isn't confirmed as owner of any unit. Please contact your building manager" />}
{status !== "not allowed" && {status !== "not allowed" &&
<Card> <Card>
<Typography sx={classes.subheader}>Tekuće glasanje</Typography> <Typography sx={classes.subheader}>{t('Current voting')}</Typography>
{status === "no voting" && <Typography>U ovom trenutku nema aktivnog glasanja.</Typography>} {status === "no voting" && <Typography>{t('There is no active voting at the moment')}.</Typography>}
{status === "in progress" && {status === "in progress" &&
<> <>
<Typography sx={classes.subject}>{voting.subject}</Typography> <Typography sx={classes.subject}>{voting.subject}</Typography>
<FormControl> <FormControl>
<FormLabel>Opcije</FormLabel> <FormLabel>{t('Options')}</FormLabel>
<RadioGroup value={selectedCandidateId} onChange={(event) => { setSelectedCandidateId(event.target.value) }}> <RadioGroup value={selectedCandidateId} onChange={(event) => { setSelectedCandidateId(event.target.value) }}>
{voting.candidates.map((candidate, ind: number) => (<FormControlLabel value={candidate._id} control={<Radio size="small" />} label={candidate.name} key={ind} />))} {voting.candidates.map((candidate, ind: number) => (<FormControlLabel value={candidate._id} control={<Radio size="small" />} label={candidate.name} key={ind} />))}
</RadioGroup> </RadioGroup>
</FormControl> </FormControl>
<Button variant='contained' sx={classes.button} disabled={selectedCandidateId === ''} onClick={handleVote}>Glasaj</Button> <Button variant='contained' sx={classes.button} disabled={selectedCandidateId === ''} onClick={handleVote}>{t("Vote")}</Button>
</> </>
} }
{status === "voted" && <Typography>Hvala vam na glasanju. </Typography>} {status === "voted" && <Typography>{t('Thank you for voting')}. </Typography>}
</Card> </Card>
} }
</> </>
} }
{ {
!privateKey && <Warning text='Glasanje je onemogućeno jer privatan ključ nije sačuvan u aplikaciji. Molimo vas, podesite ključ u podešavanjima!' /> !privateKey && <Warning text={t("Voting is disabled because private key isn't saved in application. Please, set up key in settings")} />
} }
</TabWrapper> </TabWrapper>
} }
......
import { Typography } from "@mui/material"; import { Typography } from "@mui/material";
import { Box } from "@mui/system"; import { Box } from "@mui/system";
import { useTranslation } from "react-i18next";
import { WarningIcon } from "../icons/WarningIcon"; import { WarningIcon } from "../icons/WarningIcon";
const classes = { const classes = {
...@@ -16,11 +17,14 @@ const classes = { ...@@ -16,11 +17,14 @@ const classes = {
} }
} as const; } as const;
export const Warning = ({text}: {text: string}) => { export const Warning = ({ text }: { text: string }) => {
const { t } = useTranslation();
return ( return (
<Box sx={classes.wrapper}> <Box sx={classes.wrapper}>
<WarningIcon /> <WarningIcon />
<Typography>{text}</Typography> <Typography>{t(text)}.</Typography>
</Box> </Box>
); );
} }
\ No newline at end of file
...@@ -70,30 +70,34 @@ const classes = { ...@@ -70,30 +70,34 @@ const classes = {
zIndex: 3 zIndex: 3
}, },
},
menuPaper: {
maxHeight: '250px'
}, },
voting: { voting: {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
gap: '20px' gap: '20px'
}, },
digitalVoting: { digitalVoting: {
color: 'rgb(30, 41, 60)' color: 'rgb(30, 41, 60)'
}, },
popperWrapper: { popperWrapper: {
display: 'flex', display: 'flex',
alignItems: 'center' alignItems: 'center'
}, },
helperCloud: { helperCloud: {
width: '300px', width: '300px',
backgroundColor: 'rgba(255,255,255,1)', backgroundColor: 'rgba(255,255,255,1)',
padding: 2, padding: 2,
borderRadius: 5, borderRadius: 5,
boxShadow: 'rgba(0, 0, 0, 0.24) 0px 3px 8px', boxShadow: 'rgba(0, 0, 0, 0.24) 0px 3px 8px',
userSelect: 'none' userSelect: 'none'
}, },
helperText: { helperText: {
color: 'rgb(30, 41, 60)', color: 'rgb(30, 41, 60)',
fontSize: '0.8rem' fontSize: '0.8rem'
}, },
registerButton: { registerButton: {
alignSelf: 'flex-end', alignSelf: 'flex-end',
...@@ -269,13 +273,14 @@ export const RegisterForm = (): JSX.Element => { ...@@ -269,13 +273,14 @@ export const RegisterForm = (): JSX.Element => {
}} }}
/> />
</Box> </Box>
<FormControl fullWidth size="small" onKeyUp={(e) => { e.stopPropagation(); }}> <FormControl fullWidth sx={{ maxHeight: '50px' }} size="small" onKeyUp={(e) => { e.stopPropagation(); }}>
<InputLabel>Select your units</InputLabel> <InputLabel>Select your units</InputLabel>
<Select <Select
label="Select your units" label="Select your units"
sx={classes.select} sx={classes.select}
value={registerInfo.pendingBuildings.units} value={registerInfo.pendingBuildings.units}
multiple multiple
MenuProps={{ sx: classes.menuPaper }}
onChange={(e) => { onChange={(e) => {
let units: string[] = typeof e.target.value === 'string' ? e.target.value.split(',') : e.target.value; let units: string[] = typeof e.target.value === 'string' ? e.target.value.split(',') : e.target.value;
setRegisterInfo({ ...registerInfo, pendingBuildings: { ...registerInfo.pendingBuildings, units } }) setRegisterInfo({ ...registerInfo, pendingBuildings: { ...registerInfo.pendingBuildings, units } })
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
"Main menu": "Main menu", "Main menu": "Main menu",
"Overview": "Overview", "Overview": "Overview",
"Notifications": "Notifications", "Notifications": "Notifications",
"Activities": "Activities", "Issues": "Issues",
"Voting": "Voting", "Voting": "Voting",
"Accounts/Finance": "Accounts/Finance", "Accounts/Finance": "Accounts/Finance",
"My account": "My account", "My account": "My account",
...@@ -15,11 +15,25 @@ ...@@ -15,11 +15,25 @@
"Application": "Application", "Application": "Application",
"Settings": "Settings", "Settings": "Settings",
"Currently there are not notifications for this unit": "Currently there are not notifications for this unit",
"Description": "Description",
"Currently there are not issues for this unit": "Currently there are not issues for this unit",
"Description was not provided.": "Description was not provided.",
"Solutions": "Solutions",
"You account isn't confirmed as owner of any unit. Please contact your building manager": "You account isn't confirmed as owner of any unit. Please contact your building manager",
"Current voting": "Current voting",
"Voting is disabled because private key isn't saved in application. Please, set up key in settings": "Voting is disabled because private key isn't saved in application. Please, set up key in settings",
"There is no active voting at the moment": "There is no active voting at the moment",
"Options": "Options",
"Vote": "Vote",
"Thank you for voting": "Thank you for voting",
"My Account": "My Account",
"No records": "No records",
"Invoice Id": "Invoice Id", "Invoice Id": "Invoice Id",
"Payables": "Payables", "Payables": "Payables",
"Date": "Datum", "Date": "Date",
"Accounting": "Accounting", "Accounting": "Accounting",
"Total": "Total", "Total": "Total",
"Status": "Status", "Status": "Status",
...@@ -28,6 +42,20 @@ ...@@ -28,6 +42,20 @@
"nalog": "{{num, nalog}}", "nalog": "{{num, nalog}}",
"per group/per unit":"per group", "per group/per unit":"per group",
"per unit/per unit": "per unit", "per unit/per unit": "per unit",
"per unit/per area": "per area" "per unit/per area": "per area",
"Name": "Name",
"Action": "Action",
"No documents": "No documents",
"If you want to participate in voting you need to generate voting keys and save them in application": "If you want to participate in voting you need to generate voting keys and save them in application",
"Private key": "Private key",
"Invalid key": "Invalid key",
"Not allowed already set key, contact your building manager": "Not allowed already set key, contact your building manager",
"Signature not valid": "Signature not valid",
"In case you lose access to device, this key will be required to participate in voting": "In case you lose access to device, this key will be required to participate in voting",
"Private key successfully set in application": "Private key successfully set in application",
"In order to participate in voting, please enter your private key": "In order to participate in voting, please enter your private key",
"Confirm": "Confirm"
} }
} }
\ No newline at end of file
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
"Main menu": "Glavni meni", "Main menu": "Glavni meni",
"Overview": "Pregled", "Overview": "Pregled",
"Notifications": "Obaveštenja", "Notifications": "Obaveštenja",
"Activities": "Aktivnosti", "Issues": "Aktivnosti",
"Voting": "Glasanje", "Voting": "Glasanje",
"Accounts/Finance": "Računi/Finansije", "Accounts/Finance": "Računi/Finansije",
"My account": "Moj račun", "My account": "Moj račun",
...@@ -15,6 +15,23 @@ ...@@ -15,6 +15,23 @@
"Application": "Aplikacija", "Application": "Aplikacija",
"Settings": "Podešavanja", "Settings": "Podešavanja",
"Currently there are not notifications for this unit": "Trenutno nema obavestenja za ovu jedinicu",
"Description": "Opis",
"Currently there are not issues for this unit": "Trenutno nema aktivnosti za ovu jedinicu",
"Description was not provided.": "Opis rešenja nije unet.",
"Solutions": "Rešenja",
"You account isn't confirmed as owner of any unit. Please contact your building manager": "Vaš nalog nije potvrđen kao vlasnik ni jedne jedinice. Molimo obratite se upravniku stambene zajednice",
"Current voting": "Tekuće glasanje",
"Voting is disabled because private key isn't saved in application. Please, set up key in settings": "Glasanje je onemogućeno jer privatan ključ nije sačuvan u aplikaciji. Molimo vas, podesite ključ u podešavanjima",
"There is no active voting at the moment": "Trenutno nema aktivnog glasanja",
"Options": "Opcije",
"Vote": "Glasaj",
"Thank you for voting": "Hvala Vam na glasanju",
"My Account": "Moj Račun",
"No records": "Nema zapisa",
"Invoice Id": "Poziv na broj", "Invoice Id": "Poziv na broj",
"Period": "Period", "Period": "Period",
...@@ -28,7 +45,20 @@ ...@@ -28,7 +45,20 @@
"nalog": "{{num, nalog}}", "nalog": "{{num, nalog}}",
"per group/per unit":"ukupno", "per group/per unit":"ukupno",
"per unit/per unit": "po stanu", "per unit/per unit": "po stanu",
"per unit/per area": "po kvadraturi" "per unit/per area": "po kvadraturi",
"Name": "Naziv",
"Action": "Akcija",
"No documents": "Nema dokumenata",
"If you want to participate in voting you need to generate voting keys and save them in application": "Ukoliko zelite ucestvovati u glasanju potrebno je da generisete i sacuvate kljuceve u aplikaciji",
"Private key": "Privatni ključ",
"Invalid key": "Invalid ključ",
"Not allowed already set key, contact your building manager": "Ponovno podešavanje ključa nije dozvoljeno, molimo kontaktirajte upravnika zgrade",
"Signature not valid": "Potpis nije validan",
"In case you lose access to device, this key will be required to participate in voting": "U slučaju da izgubite pristup ovom uređaju, ovaj ključ će vam biti potreban kako bi na novom uređaju mogli da učestvujete u glasanju",
"Private key successfully set in application": "Privatni ključ je uspešno podešen u aplikaciji",
"In order to participate in voting, please enter your private key": "Kako bi mogli da učestvujete u glasanju, molimo vas unesite vaš privatni ključ",
"Confirm": "Potvrdi"
} }
} }
\ No newline at end of file
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