Skip to content

Commit

Permalink
Major UI refactor (#38)
Browse files Browse the repository at this point in the history
* initial commit

* selected device refact
  • Loading branch information
evertonstz authored Apr 23, 2024
1 parent 0968cdd commit be6b93d
Show file tree
Hide file tree
Showing 29 changed files with 762 additions and 40 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"clsx": "^2.1.0",
"crypto-js": "^4.2.0",
"jest-environment-jsdom": "^29.7.0",
"lodash": "^4.17.21",
"lucide-react": "^0.352.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand All @@ -35,6 +36,7 @@
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/crypto-js": "^4.2.2",
"@types/jest": "^29.5.11",
"@types/lodash": "^4.17.0",
"@types/node": "^20.11.24",
"@types/react": "^18.2.43",
"@types/react-dom": "^18.2.17",
Expand Down
11 changes: 10 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions src/components/AddDeviceFooter/AddDeviceFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useDevicesLocalStorage } from '@/hooks';
import { Pax } from '@/pax';
import { useState } from 'react';

import { SUPPORTED_DEVICES } from '../DevicesModal/constants';
import { Button } from '../ui/button';
Expand All @@ -13,6 +12,10 @@ const INPUT_PLACEHOLDER = `Insert ${SERIAL_SIZE} digits serial`;
interface Props {
onFocus?: React.FocusEventHandler<HTMLInputElement>;
onBlur?: React.FocusEventHandler<HTMLInputElement>;
serialInput?: string;
setSerialInput: React.Dispatch<React.SetStateAction<string | undefined>>;
deviceValue: Pax.lib.Devices;
setDeviceValue: React.Dispatch<React.SetStateAction<Pax.lib.Devices>>;
}

const buildOptions = (devices: Pax.lib.Devices[]) => {
Expand All @@ -29,10 +32,7 @@ const addNewDeviceButtonDisabled = (serialInput: string | undefined) => {
};

const AddDeviceFooter = (props: Props) => {
const defaultDevice = SUPPORTED_DEVICES[0];
const [serialInput, setSerialInput] = useState<string | undefined>(undefined);
const [deviceValue, setDeviceValue] =
useState<Pax.lib.Devices>(defaultDevice);
const { serialInput, setSerialInput, deviceValue, setDeviceValue } = props;

const deviceStore = useDevicesLocalStorage();

Expand Down
16 changes: 15 additions & 1 deletion src/components/DevicesModal/DevicesModal.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { Modal } from '@/components';
import { useDevicesLocalStorage } from '@/hooks';
import { Pax } from '@/pax';
import { TriangleAlert } from 'lucide-react';
import { useState } from 'react';

import AddDeviceFooter from '../AddDeviceFooter';
import DeviceCard from './DeviceCard';
import { SUPPORTED_DEVICES } from './constants';

export interface DevicesModalProps {
open: boolean;
onOpenChange: () => void;
}

const DevicesModal = ({ open, onOpenChange }: DevicesModalProps) => {
const [serialInput, setSerialInput] = useState<string | undefined>(undefined);
const defaultDevice = SUPPORTED_DEVICES[0];
const [deviceValue, setDeviceValue] =
useState<Pax.lib.Devices>(defaultDevice);
const deviceStore = useDevicesLocalStorage();

const renderCards = () => {
Expand All @@ -34,7 +41,14 @@ const DevicesModal = ({ open, onOpenChange }: DevicesModalProps) => {
};

const renderFooter = () => {
return <AddDeviceFooter />;
return (
<AddDeviceFooter
serialInput={serialInput}
setSerialInput={setSerialInput}
deviceValue={deviceValue}
setDeviceValue={setDeviceValue}
/>
);
};

return (
Expand Down
71 changes: 71 additions & 0 deletions src/components/Graphics/PaxPairingSvg/PairingLight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useEffect, useState } from 'react';

interface PairingLightProps {
radius?: string;
color: string;
speed?: 'slow' | 'normal' | 'fast';
}

const PairingLight = (props: PairingLightProps) => {
const { speed = 'normal', color, radius } = props;
const [isBloomed, setIsBloomed] = useState(false);
const getSpeed = (speed: 'fast' | 'normal' | 'slow') => {
switch (speed) {
case 'fast':
return 0.5;
case 'slow':
return 1.5;
default:
return 1;
}
};
const speedInSeconds = getSpeed(speed);

useEffect(() => {
const interval = setInterval(() => {
setIsBloomed(prevState => !prevState);
}, speedInSeconds * 1000);
return () => clearInterval(interval);
}, [speedInSeconds]);

const animationStyle: React.CSSProperties = {
width: radius ? radius : '100px',
height: radius ? radius : '100px',
borderRadius: '50%',
backgroundColor: color,
boxShadow: isBloomed ? `0 0 50px 10px ${color}` : 'none',
transition: `box-shadow ${speedInSeconds}s ease-in-out`,
animation: 'blink 1s step-end infinite',
};

const buildCircle = (x: string, y: string) => {
return (
<div
style={{
...animationStyle,
position: 'absolute',
left: x,
top: y,
transform: 'translate(-50%, -50%)',
}}
></div>
);
};

return (
<div
style={{
position: 'relative',
width: '50px',
height: '50px',
}}
>
{buildCircle('60%', '50%')}
{buildCircle('40%', '50%')}
{buildCircle('50%', '60%')}
{buildCircle('50%', '40%')}
</div>
);
};

export default PairingLight;
45 changes: 45 additions & 0 deletions src/components/Graphics/PaxPairingSvg/PaxAddSerial.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import ParallaxComponent from './ParallaxComponent';
import Pax3DeviceSvg from './Svg/Pax3DeviceSvg';
import './shakingAnimation.css';

interface Props {
parallax?: boolean;
serial?: { serial?: string; device: string };
}

const PaxAddSerial = (props: Props) => {
const svgFillColor = '#666666';

const renderWithParallax = (
multiplier: number,
children: React.ReactNode,
parallax?: boolean,
) => {
if (!parallax) {
return children;
}

return (
<ParallaxComponent multiplier={multiplier}>{children}</ParallaxComponent>
);
};

return renderWithParallax(
7,
<div className="relative flex h-72 items-center justify-center">
<div className="absolute top-14"></div>
<Pax3DeviceSvg fillColor={svgFillColor} showShadow />
<div className="absolute bottom-20">
<h1 className="text-md text-center font-bold opacity-60">
{props.serial?.device}
</h1>
</div>
<div className="absolute bottom-16">
<h1 className="text-center text-[0.6rem]">{props.serial?.serial}</h1>
</div>
</div>,
props.parallax,
);
};

export default PaxAddSerial;
15 changes: 14 additions & 1 deletion src/components/Graphics/PaxPairingSvg/PaxPairing.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import ParallaxComponent from './ParallaxComponent';
import PulsatingLight from './PulsatingLight';
import Pax3DeviceSvg from './Svg/Pax3DeviceSvg';
import './shakingAnimation.css';

interface Props {
parallax?: boolean;
pulsatingLightSpeed?: 'slow' | 'normal' | 'fast';
pairingAnimation?: boolean;
}

const PaxPairing = (props: Props) => {
const { pairingAnimation = false } = props;
const svgFillColor = '#666666';
const lightColor = '#00FFFF';

Expand All @@ -26,7 +29,17 @@ const PaxPairing = (props: Props) => {
};

return (
<div className="relative flex h-72 items-center justify-center">
<div
className="relative flex h-72 items-center justify-center"
style={
pairingAnimation
? {
animation: 'shake ease-in-out 1s alternate 2',
transformOrigin: 'bottom',
}
: {}
}
>
<div className="absolute top-14"></div>
{renderWithParallax(
7,
Expand Down
1 change: 1 addition & 0 deletions src/components/Graphics/PaxPairingSvg/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default } from './PaxPairing';
export * from './PaxAddSerial';
5 changes: 5 additions & 0 deletions src/components/Graphics/PaxPairingSvg/shakingAnimation.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@keyframes shake {
0%, 100% { transform: rotate(0deg); }
20%, 80% { transform: rotate(-10deg); }
40%, 60% { transform: rotate(10deg); }
}
1 change: 1 addition & 0 deletions src/components/Graphics/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as PaxPairing } from './PaxPairingSvg';
export { default as PaxAddSerial } from './PaxPairingSvg/PaxAddSerial';
4 changes: 3 additions & 1 deletion src/components/MainContent/MainContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ const MainContent = () => {
currentDevice: Pax.lib.PaxSerial | undefined,
) => {
return !currentDevice ? (
<NoSelectedDevice />
<div className="mx-3 flex flex-grow justify-center">
<NoSelectedDevice />
</div>
) : (
<SelectedDevice
currentDevice={currentDevice}
Expand Down
30 changes: 23 additions & 7 deletions src/components/MainContent/NoSelectedDevice.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
import { useIsMobile } from '@/hooks';
import { Pax } from '@/pax';
import { Terminal } from 'lucide-react';
import { useState } from 'react';

import AddDeviceFooter from '../AddDeviceFooter';
import { PaxPairing } from '../Graphics';
import { SUPPORTED_DEVICES } from '../DevicesModal/constants';
import { PaxAddSerial } from '../Graphics';
import { Alert, AlertDescription, AlertTitle } from '../ui/alert';

export const NoSelectedDevice = () => {
const isMobile = useIsMobile();
const [isInputOnFocus, setIsInputOnFocus] = useState(false);
const [serialInput, setSerialInput] = useState<string | undefined>(undefined);
const defaultDevice = SUPPORTED_DEVICES[0];
const [deviceValue, setDeviceValue] =
useState<Pax.lib.Devices>(defaultDevice);
return (
<div className="mx-auto flex flex-col gap-6 self-center">
<PaxPairing
<div className="flex flex-col gap-6 self-center">
<PaxAddSerial
parallax={!isMobile}
pulsatingLightSpeed={isInputOnFocus ? 'fast' : 'slow'}
serial={{ serial: serialInput, device: deviceValue }}
/>
<AddDeviceFooter
onFocus={() => setIsInputOnFocus(true)}
onBlur={() => setIsInputOnFocus(false)}
serialInput={serialInput}
setSerialInput={setSerialInput}
deviceValue={deviceValue}
setDeviceValue={setDeviceValue}
/>
<Alert>
<Terminal className="h-4 w-4" />
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
Make sure to add the correct serial from the back of your device.
</AlertDescription>
</Alert>
</div>
);
};
Loading

0 comments on commit be6b93d

Please sign in to comment.