From 61a616b7bd2874443cdd0287684fcd474624d915 Mon Sep 17 00:00:00 2001 From: Guste Gaubaite <219.guste@gmail.com> Date: Thu, 7 Aug 2025 20:20:44 +0200 Subject: [PATCH 1/4] feat: add status icons (WiFi, signal, battery) to MobilePhoneShape component --- .../front-containers/mobilephone-shape.tsx | 72 ++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/src/common/components/mock-components/front-containers/mobilephone-shape.tsx b/src/common/components/mock-components/front-containers/mobilephone-shape.tsx index 1585ee53..15760ccc 100644 --- a/src/common/components/mock-components/front-containers/mobilephone-shape.tsx +++ b/src/common/components/mock-components/front-containers/mobilephone-shape.tsx @@ -1,9 +1,10 @@ -import { forwardRef } from 'react'; -import { Group, Rect, Circle } from 'react-konva'; +import { forwardRef, useEffect, useState } from 'react'; +import { Group, Rect, Circle, Image } from 'react-konva'; import { ShapeSizeRestrictions, ShapeType } from '@/core/model'; import { ShapeProps } from '../shape.model'; import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes/shape-restrictions'; import { useGroupShapeProps } from '../mock-components.utils'; +import { loadSvgWithFill } from '@/common/utils/svg.utils'; const mobilePhoneShapeSizeRestrictions: ShapeSizeRestrictions = { minWidth: 150, @@ -37,6 +38,28 @@ export const MobilePhoneShape = forwardRef((props, ref) => { const speakerRadius = 2; const buttonRadius = 9; + const [wifiIcon, setWifiIcon] = useState(null); + const [batteryIcon, setBatteryIcon] = useState(null); + const [signalIcon, setSignalIcon] = useState(null); + + const adornerIconSize = 20; + const adornerPadding = 5; + const adornerTotalWidth = adornerIconSize * 3 + 17 * 2; + + // Calculate inner screen coordinates (excluding frame margins) + const screenX = margin + screenMargin; // Left edge of inner screen + const screenY = screenMargin * 3; // Top edge of inner screen + const screenWidth = restrictedWidth - 2 * margin - 2 * screenMargin; // Available width inside screen + + // Position adorner in top-right corner of inner screen + const adornerStartX = screenX + screenWidth - adornerTotalWidth; // Right-aligned positioning + const adornerY = screenY + adornerPadding; // Top-aligned with padding + + // Individual icon positions within the adorner + const wifiX = adornerStartX; + const signalX = adornerStartX + 17; + const batteryX = adornerStartX + 20 * 2; + const commonGroupProps = useGroupShapeProps( props, restrictedSize, @@ -44,6 +67,16 @@ export const MobilePhoneShape = forwardRef((props, ref) => { ref ); + useEffect(() => { + loadSvgWithFill('/icons/wifi.svg', 'black').then(img => setWifiIcon(img)); + loadSvgWithFill('/icons/cellsignal.svg', 'black').then(img => + setSignalIcon(img) + ); + loadSvgWithFill('/icons/batteryfull.svg', 'black').then(img => + setBatteryIcon(img) + ); + }, []); + return ( {/* Mobile Frame */} @@ -82,6 +115,41 @@ export const MobilePhoneShape = forwardRef((props, ref) => { fill="white" /> + {/* Adorner */} + + {/* Wifi */} + {wifiIcon && ( + + )} + + {/* Cell signal */} + {signalIcon && ( + + )} + + {/* Battery */} + {batteryIcon && ( + + )} + {/* Init button */} Date: Thu, 7 Aug 2025 20:29:27 +0200 Subject: [PATCH 2/4] feat: add current time display to MobilePhoneShape component --- .../front-containers/mobilephone-shape.tsx | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/common/components/mock-components/front-containers/mobilephone-shape.tsx b/src/common/components/mock-components/front-containers/mobilephone-shape.tsx index 15760ccc..dc4734ed 100644 --- a/src/common/components/mock-components/front-containers/mobilephone-shape.tsx +++ b/src/common/components/mock-components/front-containers/mobilephone-shape.tsx @@ -1,10 +1,11 @@ import { forwardRef, useEffect, useState } from 'react'; -import { Group, Rect, Circle, Image } from 'react-konva'; +import { Group, Rect, Circle, Image, Text } from 'react-konva'; import { ShapeSizeRestrictions, ShapeType } from '@/core/model'; import { ShapeProps } from '../shape.model'; import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes/shape-restrictions'; import { useGroupShapeProps } from '../mock-components.utils'; import { loadSvgWithFill } from '@/common/utils/svg.utils'; +import { BASIC_SHAPE } from '../front-components/shape.const'; const mobilePhoneShapeSizeRestrictions: ShapeSizeRestrictions = { minWidth: 150, @@ -41,10 +42,11 @@ export const MobilePhoneShape = forwardRef((props, ref) => { const [wifiIcon, setWifiIcon] = useState(null); const [batteryIcon, setBatteryIcon] = useState(null); const [signalIcon, setSignalIcon] = useState(null); + const [currentTime, setCurrentTime] = useState(''); const adornerIconSize = 20; const adornerPadding = 5; - const adornerTotalWidth = adornerIconSize * 3 + 17 * 2; + const adornerTotalWidth = adornerIconSize * 3 + 17 * 2 + 30; // Calculate inner screen coordinates (excluding frame margins) const screenX = margin + screenMargin; // Left edge of inner screen @@ -60,6 +62,10 @@ export const MobilePhoneShape = forwardRef((props, ref) => { const signalX = adornerStartX + 17; const batteryX = adornerStartX + 20 * 2; + const timeX = adornerStartX + 23 * 3; + const timeY = adornerY + 4; + const timeWidth = 40; + const commonGroupProps = useGroupShapeProps( props, restrictedSize, @@ -77,6 +83,24 @@ export const MobilePhoneShape = forwardRef((props, ref) => { ); }, []); + useEffect(() => { + const updateTime = () => { + const now = new Date(); + setCurrentTime( + now.toLocaleTimeString('es-ES', { + hour: '2-digit', + minute: '2-digit', + hour12: false, + }) + ); + }; + + updateTime(); + const timer = setInterval(updateTime, 1000); + + return () => clearInterval(timer); + }, []); + return ( {/* Mobile Frame */} @@ -150,6 +174,18 @@ export const MobilePhoneShape = forwardRef((props, ref) => { /> )} + {/* Current time */} + + {/* Init button */} Date: Thu, 7 Aug 2025 20:33:46 +0200 Subject: [PATCH 3/4] feat: increase mobilePhoneShape min width to ensure proper layout at smaller size --- .../mock-components/front-containers/mobilephone-shape.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/components/mock-components/front-containers/mobilephone-shape.tsx b/src/common/components/mock-components/front-containers/mobilephone-shape.tsx index dc4734ed..ddab3381 100644 --- a/src/common/components/mock-components/front-containers/mobilephone-shape.tsx +++ b/src/common/components/mock-components/front-containers/mobilephone-shape.tsx @@ -8,7 +8,7 @@ import { loadSvgWithFill } from '@/common/utils/svg.utils'; import { BASIC_SHAPE } from '../front-components/shape.const'; const mobilePhoneShapeSizeRestrictions: ShapeSizeRestrictions = { - minWidth: 150, + minWidth: 200, minHeight: 150, maxWidth: 1000, maxHeight: 1000, From 77e94906036ccc75c7ce16725cfabc31d6362757 Mon Sep 17 00:00:00 2001 From: Guste Gaubaite <219.guste@gmail.com> Date: Sun, 10 Aug 2025 22:14:21 +0200 Subject: [PATCH 4/4] add adorner with wifi, 5g coverage, battery and time to mobile svg --- public/containers/mobile.svg | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/public/containers/mobile.svg b/public/containers/mobile.svg index 403db18f..6c1fc8d1 100644 --- a/public/containers/mobile.svg +++ b/public/containers/mobile.svg @@ -11,6 +11,27 @@ + + + + + + + + + + + + + + + + + + + 17:00 + + \ No newline at end of file