Skip to content

Commit

Permalink
Refactor UI components and add localization support, Extract LocalSto…
Browse files Browse the repository at this point in the history
…rage Hook, Fixed Styled Props other then string
  • Loading branch information
firsttris committed Mar 4, 2024
1 parent e6a21ce commit 43cefe1
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 37 deletions.
14 changes: 8 additions & 6 deletions src/app/ChannelsForType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ import { Icon } from '@iconify/react';
import { Channel, ChannelType } from './../types/types';
import { RainDetectionControl } from './controls/RainDetectionControl';
import { DoorControl } from './controls/DoorControl';
import { useLocalStorage } from './../hooks/useLocalStorage';


interface ExpandMoreProps {
expanded: string;
expanded: boolean;
}

const ExpandMore = styled(Icon)<ExpandMoreProps>(({ expanded }) => ({
transform: expanded === 'true' ? 'rotate(180deg)' : 'rotate(0deg)',
const ExpandMore = styled(Icon, {
shouldForwardProp: (prop) => prop !== 'expanded',
})<ExpandMoreProps>(({ expanded }) => ({
transform: expanded ? 'rotate(180deg)' : 'rotate(0deg)',
marginLeft: 'auto',
transition: 'transform 150ms cubic-bezier(0.4, 0, 0.2, 1) 0ms',
fontSize: '25px',
Expand Down Expand Up @@ -86,10 +89,9 @@ export const ChannelsForType: React.FC<ChannelTypeProps> = ({
const [hasTransitionExited, setHasTransitionExited] = useState<
boolean
>(true);
const [expanded, setExpanded] = useState<boolean>(localStorage.getItem(channelType) === 'true');
const [expanded, setExpanded] = useLocalStorage(channelType, false);

const handleExpandClick = () => {
localStorage.setItem(channelType, (!expanded).toString());
setExpanded(!expanded)
};

Expand All @@ -113,7 +115,7 @@ export const ChannelsForType: React.FC<ChannelTypeProps> = ({
>
{t(channelType)}
</Typography>
<ExpandMore icon="uiw:down" expanded={expanded.toString()}/>
<ExpandMore icon="uiw:down" expanded={expanded}/>
</ListItemButton>
</ListItem>
{hasTransitionExited ? <Divider /> : null}
Expand Down
2 changes: 1 addition & 1 deletion src/app/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const Login = () => {
</Box>
<Box sx={{ mt: 6 }}>
<Button type="submit" value="submit" variant="contained" fullWidth>
Sign in
{t('SIGN_IN')}
</Button>
</Box>
</form>
Expand Down
6 changes: 3 additions & 3 deletions src/app/components/StyledIcons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { styled } from "@mui/material";

interface StyledIconButtonProps {
icon: string;
active?: string;
active?: boolean;
}

export const StyledIconButton = styled(Icon)<StyledIconButtonProps>`
color: ${(props) => (props.active === 'true' ? '#0077B6' : '#000')};
export const StyledIconButton = styled(Icon, { shouldForwardProp: (prop) => prop !== 'active', })<StyledIconButtonProps>`
color: ${(props) => (props.active ? '#0077B6' : '#000')};
font-size: 40px;
background-color: lightGrey;
border-radius: 10px;
Expand Down
18 changes: 11 additions & 7 deletions src/app/controls/DoorControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { StyledIconButton } from '../components/StyledIcons';
import { KeymaticChannel } from './../../types/types';
import { useSetValueMutation } from './../../hooks/useApi';
import { styled } from '@mui/system';
import { useTranslations } from './../../i18n/utils';

const StyledOuterBox = styled(Box)({
display: 'flex',
Expand All @@ -17,10 +18,12 @@ const StyledOuterBox = styled(Box)({
});

interface StyledTypographyProps {
uncertain: string;
uncertain: boolean
}
const StyledTypography = styled(Typography)<StyledTypographyProps>(({ uncertain }) => ({
display: uncertain === 'true' ? 'block' : 'none',
const StyledTypography = styled(Typography, {
shouldForwardProp: (prop) => prop !== 'uncertain',
})<StyledTypographyProps>(({ uncertain }) => ({
display: uncertain ? 'block' : 'none',
}));

interface DoorControlProps {
Expand All @@ -29,6 +32,7 @@ interface DoorControlProps {
}

export const DoorControl: React.FC<DoorControlProps> = ({ channel, refetch }) => {
const t = useTranslations();
const setValueMutation = useSetValueMutation();
const {
datapoints: { STATE, STATE_UNCERTAIN },
Expand Down Expand Up @@ -77,12 +81,12 @@ export const DoorControl: React.FC<DoorControlProps> = ({ channel, refetch }) =>
<StyledInnerBox>
<StyledIconButton
icon="material-symbols:lock-outline"
active={(!isUnlocked).toString()}
active={!isUnlocked}
onClick={lockDoor}
/>
<StyledIconButton
icon="material-symbols:lock-open-outline"
active={isUnlocked.toString()}
active={isUnlocked}
onClick={unlockDoor}
/>
<StyledIconButton
Expand All @@ -91,10 +95,10 @@ export const DoorControl: React.FC<DoorControlProps> = ({ channel, refetch }) =>
/>
</StyledInnerBox>
<StyledTypography
uncertain={isUncertain.toString()}
uncertain={isUncertain}
variant="caption"
>
Door state is uncertain
{t('DOOR_STATE_UNKNOWN')}
</StyledTypography>
</StyledOuterBox>
}
Expand Down
36 changes: 21 additions & 15 deletions src/app/controls/RainDetectionControl.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { Box, CardHeader, Typography, styled } from '@mui/material';
import { RainDetectionTransmitterChannel } from './../../types/types';
import { StyledHeaderIcon } from '../components/StyledIcons';
import { useTranslations } from './../../i18n/utils';

const StyledBox = styled(Box)({
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
width: '100%',
gap: '20px'
});

const StyledIconBox = styled(Box)({
display: 'flex',
alignItems: 'center',
gap: '5px',
});

display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
width: '100%',
gap: '20px',
});

const StyledIconBox = styled(Box)({
display: 'flex',
alignItems: 'center',
gap: '5px',
});

interface RainDetectionControlProps {
channel: RainDetectionTransmitterChannel;
Expand All @@ -30,6 +30,8 @@ export const RainDetectionControl: React.FC<RainDetectionControlProps> = ({

const isRaining = RAINING === 'true';
const isHeating = HEATER_STATE === 'true';

const t = useTranslations();

return (
<CardHeader
Expand All @@ -41,7 +43,9 @@ export const RainDetectionControl: React.FC<RainDetectionControlProps> = ({
) : (
<StyledHeaderIcon icon="mdi:clouds" />
)}
<Typography variant="caption">{isRaining ? 'Raining' : 'Not Raining'}</Typography>
<Typography variant="caption">
{isRaining ? t('RAINING') : t('NOT_RAINING')}
</Typography>
</StyledIconBox>
<StyledIconBox>
{isHeating ? (
Expand All @@ -52,7 +56,9 @@ export const RainDetectionControl: React.FC<RainDetectionControlProps> = ({
) : (
<StyledHeaderIcon icon="material-symbols:mode-heat-off" />
)}
<Typography variant="caption">{isHeating ? 'Heating' : 'Not Heating'}</Typography>
<Typography variant="caption">
{isHeating ? t('HEATING') : t('NOT_HEATING')}
</Typography>
</StyledIconBox>
</StyledBox>
}
Expand Down
11 changes: 7 additions & 4 deletions src/app/controls/SwitchControl.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { styled } from '@mui/system';
import { Box } from '@mui/material';
import {
useSetValueMutation,
} from '../../hooks/useApi';
import { useSetValueMutation } from '../../hooks/useApi';
import { ChannelHeader } from '../components/ChannelHeader';
import { SwitchVirtualReceiverChannel } from 'src/types/types';

Expand Down Expand Up @@ -38,7 +36,12 @@ export const SwitchControl = ({ channel, refetch }: ControlProps) => {

return (
<StyledBox>
<ChannelHeaderWithPointer name={name} icon={checked ? 'mdi:light-switch' : 'mdi:light-switch-off'} color={checked ? 'orange' : 'unset'} onClick={onHandleChange} />
<ChannelHeaderWithPointer
name={name}
icon={checked ? 'mdi:light-switch' : 'mdi:light-switch-off'}
color={checked ? 'orange' : 'unset'}
onClick={onHandleChange}
/>
</StyledBox>
);
};
2 changes: 1 addition & 1 deletion src/app/controls/ThermostatControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface ControlProps {
channel: HeatingClimateControlTransceiverChannel;
}

const StyledButton = styled('button')(({ theme }) => ({
const StyledButton = styled('button')(() => ({
backgroundColor: 'lightgrey',
fontWeight: 'bold',
borderRadius: '10px',
Expand Down
25 changes: 25 additions & 0 deletions src/hooks/useLocalStorage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useState } from 'react';

export const useLocalStorage = (key: string, initialValue: boolean): [boolean, (value: boolean) => void] => {

const [storedValue, setStoredValue] = useState<boolean>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.log(error);
return initialValue;
}
});

const setValue = (value: boolean) => {
try {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.log(error);
}
};

return [storedValue, setValue];
}
12 changes: 12 additions & 0 deletions src/i18n/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ export const ui = {
KEYMATIC: 'Keymatic',
errorOccuredWhileLogin: 'Error occured while login',
signInTitle: 'Sign in',
RAINING: 'Raining',
NOT_RAINING: 'Not Raining',
HEATING: 'Heating',
NOT_HEATING: 'Not Heating',
DOOR_STATE_UNKNOWN: 'Door state is uncertain',
SIGN_IN: 'Sign in',
},
de: {
SWITCH_VIRTUAL_RECEIVER: 'Schalter',
Expand All @@ -28,6 +34,12 @@ export const ui = {
KEYMATIC: 'Keymatic',
errorOccuredWhileLogin: 'Fehler beim Login',
signInTitle: 'Anmelden',
RAINING: 'Regen',
NOT_RAINING: 'Kein Regen',
HEATING: 'Heizen',
NOT_HEATING: 'Nicht Heizen',
DOOR_STATE_UNKNOWN: 'Türzustand ist ungewiss',
SIGN_IN: 'Anmelden',
},
} as const;

Expand Down

0 comments on commit 43cefe1

Please sign in to comment.