Skip to content

Commit

Permalink
feat(app): Energy widget adjusted for more sizes
Browse files Browse the repository at this point in the history
  • Loading branch information
AleksandarDev committed Aug 12, 2024
1 parent 1a4fdac commit 94f45db
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export function UsageCurrent() {
width={500}
height={300}
discrete
aggregate
aggregate={1}
limits={[
{ id: 'executions', value: limit }
]} />
Expand Down
4 changes: 2 additions & 2 deletions web/apps/app/components/widgets/parts/Wave.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function Wave({ value, breakpoints }: { value: number, breakpoints: reado
// 'fill-red-400'
)}
style={{
'--wave-height': `${value}px`,
'--wave-height': `${value}%`,
} as CSSProperties}>
<SingleWave />
<SingleWave />
Expand All @@ -39,7 +39,7 @@ export function Wave({ value, breakpoints }: { value: number, breakpoints: reado
value >= breakpoints[2] && 'bg-rose-500 dark:bg-rose-700',
)}
style={{
'--wave-height': `${value}px`
'--wave-height': `${value}%`
} as CSSProperties}></div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ function WidgetAirConditioning(props: WidgetSharedProps<ConfigProps>) {
height={rows * 25 - 2}
hideLegend
adaptiveDomain
aggregate={30 * 60 * 1000}
/>
</div>
</div>
Expand Down
95 changes: 62 additions & 33 deletions web/apps/app/components/widgets/parts/WidgetEnergy.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMemo } from 'react';
import { ComponentProps, useMemo } from 'react';
import { Typography } from '@signalco/ui-primitives/Typography';
import { cx } from '@signalco/ui-primitives/cx';
import { Loadable } from '@signalco/ui/Loadable';
Expand Down Expand Up @@ -32,20 +32,31 @@ const stateOptions: IWidgetConfigurationOption<ConfigProps>[] = [
DefaultColumns(4)
];

function UsageIndicatorCircle({ value, percentageValue, unit, largeValue }: { value: number, percentageValue: number, unit: string, largeValue?: boolean }) {
function UsageIndicatorCircle({ value, percentageValue, unit, largeValue, size, fullSize }: {
value: number,
percentageValue: number,
unit: string,
largeValue?: boolean,
size?: 'small' | 'normal' | 'large',
fullSize?: boolean
}) {
const breakpoints = [10, 30, 60] as const;
return (
<div className="relative">
<div className={cx('relative', fullSize && 'size-full')}>
<div className={cx(
'relative flex h-32 w-32 items-center justify-center overflow-hidden rounded-full border-2',
'relative flex items-center justify-center overflow-hidden',
!fullSize ? 'rounded-full border-2' : 'w-full h-full',
(!fullSize && (!size || size === 'normal')) && 'h-32 w-32',
(!fullSize && size === 'small') && 'h-16 w-16',
(!fullSize && size === 'large') && 'h-44 w-44',
percentageValue < breakpoints[0] && 'border-green-200 dark:border-green-500',
percentageValue >= breakpoints[0] && percentageValue < breakpoints[1] && 'border-lime-200 dark:border-lime-700',
percentageValue >= breakpoints[1] && percentageValue < breakpoints[2] && 'border-amber-200 dark:border-amber-700',
percentageValue >= breakpoints[2] && 'border-rose-300 dark:border-rose-900'
)}>
<Wave value={percentageValue} breakpoints={breakpoints} />
<div className={cx('z-10 text-center', largeValue && 'ml-6')}>
<PrimaryValueLabel value={value} unit={unit} size="small" />
<PrimaryValueLabel value={value} unit={unit} size={size ?? 'normal'} />
</div>
</div>
</div>
Expand All @@ -72,44 +83,62 @@ export default function WidgetEnergy({ config, onOptions }: WidgetSharedProps<Co
const label = config?.label ?? '';
const isLargeValue = usageWats >= 1000;
const unit = isLargeValue ? 'kW/h' : 'W/h';
const usageHumanized = usageWats >= 1000 ? usageWats / 1000 : Math.round(usageWats);
const usageHumanized = isLargeValue ? usageWats / 1000 : Math.round(usageWats);
const percentageValue = Math.max(0, Math.min(100, usageWats / maxUsage)) * 100;

const isSmall = rows <= 2 || columns <= 2;
const isTiny = rows <= 1 || columns <= 1;
const indicatorSize = rows > 3 && columns > 3 ? 'large' : (!isSmall ? 'normal' : 'small');

return (
<Loadable
contentVisible
isLoading={isLoading}
loadingLabel="Loading"
error={errors}
className="items-end">
<div className="absolute inset-0 px-6 py-4">
<Typography semiBold noWrap>{label}</Typography>
</div>
<div className="flex w-full flex-col items-center p-6">
<UsageIndicatorCircle value={usageHumanized} percentageValue={percentageValue} unit={unit} largeValue={isLargeValue} />
</div>
<Loadable
contentVisible
isLoading={historyData.isLoading}
loadingLabel="Loading"
error={historyData.error}
className="absolute inset-x-0 bottom-0">
<div className="absolute inset-x-0 bottom-0">
<Graph
isLoading={historyData.isLoading}
error={historyData.error}
data={historyData.item?.at(0)?.history?.map(i => ({
id: i.timeStamp.toUTCString(),
value: i.valueSerialized ?? ''
})) ?? []}
durationMs={duration}
width={columns * 84 - 2}
height={rows * 25}
hideLegend
adaptiveDomain
/>
{!isTiny && (
<div className="absolute inset-0 p-2">
<Typography semiBold noWrap level="body1">{label}</Typography>
</div>
</Loadable>
)}
<div className={cx(
'w-full h-full',
!isTiny && 'flex flex-col pb-3 justify-center items-center',
)}>
<UsageIndicatorCircle
value={usageHumanized}
percentageValue={percentageValue}
unit={unit}
largeValue={isLargeValue}
size={indicatorSize}
fullSize={isTiny} />
</div>
{!isTiny && (
<Loadable
contentVisible
isLoading={historyData.isLoading}
loadingLabel="Loading"
error={historyData.error}
className="absolute inset-x-0 bottom-0">
<div className="absolute inset-x-0 bottom-0">
<Graph
isLoading={historyData.isLoading}
error={historyData.error}
data={historyData.item?.at(0)?.history?.map(i => ({
id: i.timeStamp.toUTCString(),
value: i.valueSerialized ?? ''
})) ?? []}
durationMs={duration}
width={columns * 84 - 2}
height={rows * 25}
hideLegend
adaptiveDomain
aggregate={60 * 60 * 1000}
/>
</div>
</Loadable>
)}
</Loadable>
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Typography } from '@signalco/ui-primitives/Typography';
import { Stack } from '@signalco/ui-primitives/Stack';
import { Row } from '@signalco/ui-primitives/Row';
import { cx } from '@signalco/ui-primitives/cx';

export function numberWholeAndDecimal(data: number | string | undefined): [undefined, undefined] | [number, number] {
if (typeof data === 'undefined')
Expand All @@ -17,16 +16,18 @@ export function numberWholeAndDecimal(data: number | string | undefined): [undef
];
}

export function PrimaryValueLabel({ value, unit, size }: { value: number | string | undefined; unit: string; size: 'small' | 'large'; }) {
const [degreesWhole, degreesDecimal] = numberWholeAndDecimal(value);
export function PrimaryValueLabel({ value, unit, size = 'normal' }: { value: number | string | undefined; unit: string; size: 'small' | 'normal' | 'large'; }) {
const [valueWhole, degreesDecimal] = numberWholeAndDecimal(value);
const valueTextSize = (size === 'large' ? 'text-6xl' : (size === 'normal' ? 'text-5xl' : 'text-4xl'));
const detailsTextSize = (size === 'large' ? 'text-lg' : (size === 'normal' ? 'text-base' : 'text-sm'));
return (
<Row alignItems="stretch">
<Stack className="h-full" justifyContent="center" alignItems="center">
<Typography extraThin className={cx(size === 'large' ? 'text-6xl' : 'text-4xl')}>{degreesWhole}</Typography>
<Typography extraThin className={valueTextSize}>{valueWhole}</Typography>
</Stack>
<Stack alignItems="start" justifyContent="space-between">
<Typography extraThin className={size === 'large' ? 'text-lg' : 'text-xs'} tertiary>{unit}</Typography>
<Typography extraThin className={size === 'large' ? 'text-lg' : 'text-sm'} tertiary>.{degreesDecimal}</Typography>
<Typography extraThin className={detailsTextSize} tertiary>{unit}</Typography>
<Typography extraThin className={detailsTextSize} tertiary>.{degreesDecimal}</Typography>
</Stack>
</Row>
);
Expand Down

0 comments on commit 94f45db

Please sign in to comment.