diff --git a/src/components/ControlSection.tsx b/src/components/ControlSection.tsx new file mode 100644 index 0000000..27574f2 --- /dev/null +++ b/src/components/ControlSection.tsx @@ -0,0 +1,33 @@ +import { ReactNode } from "react"; + +interface ControlSectionProps { + title: string; + description?: string; + id?: string; + stack: ReactNode; + colSpan?: number; + stackType?: 'grid' | 'flex' +} + +export default function ControlSection ({ + title, + description, + id, + stack +}: ControlSectionProps) { + return ( +
+
+
+

+ {title} +

+

{description}

+
+ {stack} +
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/components/MainBody.tsx b/src/components/MainBody.tsx index dc6a802..7ec0152 100644 --- a/src/components/MainBody.tsx +++ b/src/components/MainBody.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode } from "react"; +import { ReactNode } from "react"; import BackroundImg from "../assets/img/background.png"; export default function MainBody({ children }: { children?: ReactNode }) { diff --git a/src/components/forms/EvoInput.tsx b/src/components/forms/EvoInput.tsx new file mode 100644 index 0000000..5797456 --- /dev/null +++ b/src/components/forms/EvoInput.tsx @@ -0,0 +1,38 @@ +import { ChangeEventHandler, HTMLInputTypeAttribute, useRef } from "react"; + +interface EvoInputProps { + className?: string; + name: string; + value: string; + type?: HTMLInputTypeAttribute + onChange?: ChangeEventHandler +} + +export default function EvoInput ({ + className, + name, + value, + type, + onChange +}: EvoInputProps) { + const labelRef = useRef(null); + + const handleClick = () => { + labelRef.current?.focus(); + } + + return ( + + ) +} \ No newline at end of file diff --git a/src/components/forms/PinBox.tsx b/src/components/forms/PinBox.tsx index dcb42d8..b15e43d 100644 --- a/src/components/forms/PinBox.tsx +++ b/src/components/forms/PinBox.tsx @@ -2,27 +2,53 @@ import { ChangeEventHandler, FormEventHandler, MouseEventHandler } from "react"; import Switch from "./Switch"; interface PinBoxProps { + className?: string; value: number | string; state: boolean; - onValueChange?: ChangeEventHandler - onStateChange?: FormEventHandler + onValueChange?: ChangeEventHandler; + onStateChange?: FormEventHandler; + onDelete?: FormEventHandler; + minusBtn?: boolean; } -function Add ({ onClick }: { onClick?: MouseEventHandler }) { +function Add ({ + className, + onClick +}: { + className?: string, + onClick?: MouseEventHandler +}) { return ( - ) } -function PinBox ({ value, state, onValueChange, onStateChange }: PinBoxProps) { +function PinBox ({ + className, + value, + state, + onValueChange, + onStateChange, + onDelete, + minusBtn +}: PinBoxProps) { return ( -
-
-
Pin
+
+ {minusBtn && } +
+
+ Pin +
{ let anopin = 13; for (let i = 0; i < leds.length; i++) { - // console.log(leds[i].pin != anopin, leds[i].pin, anopin); - if (leds[i].pin != anopin) break; - anopin--; + if (leds.filter(led => led.pin == anopin).length > 0) { + anopin--; + } + else break; } addLed(anopin, false); } return ( -
-
-
-

- LED -

-
- {leds.map((led, i) => ( - { - const pin = e.target.value; - if (leds.filter(led => led.pin == pin).length > 0) { - alert(`Pin ${pin} is already use`); - return; - } - setLedPin(led.pin, pin); - }} - onStateChange={() => { - const state = !led.state; - setLed(led.pin, state); - }} - /> - ))} - {leds.length < 14 && } -
-
-
-
+ + {leds.map((led, i) => ( + { + const pin = e.target.value; + setLedPin(i, pin); + }} + onStateChange={() => { + const state = !led.state; + setLed(led.pin, state); + }} + onDelete={() => { + removeLed(i); + }} + /> + ))} + {leds.length < 14 && } + )} + /> ) } diff --git a/src/components/landing/ControlRgbLed.tsx b/src/components/landing/ControlRgbLed.tsx new file mode 100644 index 0000000..1c73e98 --- /dev/null +++ b/src/components/landing/ControlRgbLed.tsx @@ -0,0 +1,174 @@ +import { useRgbLed } from "../../hooks"; +import { ChannelPinState, PinState } from "../../types/board"; +import EvoInput from "../forms/EvoInput"; +import Switch from "../forms/Switch"; +import { MouseEventHandler, useEffect, useState } from "react"; + +interface HorizontalBarProps { + pinState: ChannelPinState; + onUpdate?: (pin: ChannelPinState) => void; + onDelete?: () => void +} + +function HorizontalBar ({ pinState, onUpdate, onDelete }: HorizontalBarProps) { + const [red, setRed] = useState({ + pin: pinState.red.pin.toString(), + state: pinState.red.state + }); + + const [green, setGreen] = useState({ + pin: pinState.green.pin.toString(), + state: pinState.green.state + }); + + const [blue, setBlue] = useState({ + pin: pinState.blue.pin.toString(), + state: pinState.blue.state + }); + + useEffect(() => { + if (onUpdate) onUpdate({red, green, blue}); + }, [red, green, blue]) + + return ( +
+ +
+
+
Red
+ { + setRed({ + pin: e.target.value, + state: red.state + }); + }} + /> + { + setRed({ + pin: red.pin, + state: !red.state + }) + }} + /> +
+
+
Green
+ { + setGreen({ + pin: e.target.value, + state: green.state + }); + }} + /> + { + setGreen({ + pin: green.pin, + state: !green.state + }) + }} + /> +
+
+
Blue
+ { + setBlue({ + pin: e.target.value, + state: blue.state + }); + }} + /> + { + setBlue({ + pin: blue.pin, + state: !blue.state + }) + }} + /> +
+
+
+ ) +} + +function HorizontalBarPlus ({ onClick }: { onClick?: MouseEventHandler }) { + return ( + + ) +} + +function ControlRgbLed () { + const { addLed, rgbLed, removeLed, setLed } = useRgbLed(); + + const handleAdd = (): void => { + addLed({ + red: { + pin: 13, + state: false + }, + green: { + pin: 12, + state: false + }, + blue: { + pin: 11, + state: false + } + }) + } + + return ( +
+
+
+

+ RGB LED +

+
+ {rgbLed.map((led, i) => ( + { + setLed(i, newLed); + }} + onDelete={() => { + removeLed(i); + }} + /> + ))} + {rgbLed.length < 5 && } +
+
+
+
+ ) +} + +export default ControlRgbLed; \ No newline at end of file diff --git a/src/components/landing/Hero.tsx b/src/components/landing/Hero.tsx index 2098546..1c32938 100644 --- a/src/components/landing/Hero.tsx +++ b/src/components/landing/Hero.tsx @@ -24,13 +24,17 @@ function Hero ({ img, shortNav }: InHero) { i don't even know anything about electronics and some IoT stuff lol

- {shortNav.map(({ name }, i) => ( - + {shortNav.map(({ name, target }, i) => ( + + + ))}
Made By - + + + Norman Andrians
diff --git a/src/contexts/BoardController.tsx b/src/contexts/BoardController.tsx index 4164cdf..1333450 100644 --- a/src/contexts/BoardController.tsx +++ b/src/contexts/BoardController.tsx @@ -24,7 +24,22 @@ const INIT_VALUES: ControllerContextProps = { state: false } ], - rgbLed: [], + rgbLed: [ + { + red: { + pin: 13, + state: false + }, + green: { + pin: 12, + state: false + }, + blue: { + pin: 11, + state: false + } + } + ], piezo: [], motoServo: [], photoresistor: [], diff --git a/src/css/index.css b/src/css/index.css index 72e75db..27a2753 100644 --- a/src/css/index.css +++ b/src/css/index.css @@ -5,6 +5,9 @@ @tailwind utilities; @layer base { + html { + scroll-behavior: smooth; + } input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { -webkit-appearance: none; @@ -27,6 +30,14 @@ to { opacity: 1; } } +@keyframes wewew { + 0% { transform: scale(1, 1); } + 25% { transform: scale(1.1, .9); } + 50% { transform: scale(.9, 1.1); } + 75% { transform: scale(1.1, .9); } + 100% { transform: scale(1, 1); } +} + .container { @apply w-[1280px] mx-auto; } @@ -36,10 +47,10 @@ } .switch { - @apply rounded-lg; + @apply rounded-lg transition; } .switch > .handler { - @apply rounded-md p-[6px] transition-all; + @apply rounded-md p-[6px] transition-[margin]; } @@ -51,7 +62,7 @@ } .switch-off { - @apply border-disabled; + @apply border-disabled bg-transparent; } .switch-off > .handler { @apply bg-disabled ms-0; diff --git a/src/hooks/index.tsx b/src/hooks/index.tsx index a0cbc07..fe72c6f 100644 --- a/src/hooks/index.tsx +++ b/src/hooks/index.tsx @@ -1,5 +1,6 @@ import { useContext } from "react"; import { BoardControllerContext } from "../contexts/BoardController"; +import { ChannelPinState } from "../types/board"; export function usePin () { return useContext(BoardControllerContext); @@ -18,8 +19,8 @@ export function useLed () { setLeds!(newLed); } - const removeLed = (pin: number | string) => { - const newLed = leds.filter(led => led.pin != pin); + const removeLed = (index: number) => { + const newLed = leds.filter((_led, i) => i != index); setLeds!(newLed); } @@ -31,13 +32,51 @@ export function useLed () { setLeds!(newLed); } - const setLedPin = (pin: number | string, newPin: number | string) => { - const newLed = leds.map(led => { - if (led.pin == pin) return { pin: newPin, state: led.state }; + const setLedPin = (index: number | string, newPin: number | string) => { + const newLed = leds.map((led, i) => { + if (i == index) return { pin: newPin, state: led.state }; return led; }) setLeds!(newLed); } return { leds, getLed, setLed, setLedPin, addLed, removeLed }; +} + + + +export function useRgbLed () { + const { rgbLed, setRgbLed } = useContext(BoardControllerContext); + + const getLed = (index: number) => { + const led = rgbLed.find((_val, i) => i == index); + return led; + } + + const addLed = (channelPin: ChannelPinState) => { + const newLed: ChannelPinState[] = [ + ...rgbLed, + { + red: channelPin.red, + green: channelPin.green, + blue: channelPin.blue + } + ]; + setRgbLed!(newLed); + } + + const removeLed = (index: number) => { + const newLed: ChannelPinState[] = rgbLed.filter((_led, i) => i != index); + setRgbLed!(newLed); + } + + const setLed = (index: number, channelPin: ChannelPinState) => { + const newLed: ChannelPinState[] = rgbLed.map((led, i) => { + if (i == index) return channelPin; + return led; + }) + setRgbLed!(newLed); + } + + return { rgbLed, getLed, setLed, addLed, removeLed }; } \ No newline at end of file diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx index 560b2a8..af6c057 100644 --- a/src/pages/MainPage.tsx +++ b/src/pages/MainPage.tsx @@ -7,6 +7,7 @@ import ControlLED from "../components/landing/ControlLED"; import LunarImg from "../assets/img/ocs/lunar-oc.png"; import ControlNav from "../data/control-navigation.json"; +import ControlRgbLed from "../components/landing/ControlRgbLed"; function MainPage () { return (<> @@ -16,6 +17,7 @@ function MainPage () { shortNav={ControlNav} /> + ) } diff --git a/tailwind.config.js b/tailwind.config.js index 66f7f83..920f2b2 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -23,7 +23,8 @@ export default { }, animation: { 'size-in': 'size-in .3s ease-in-out', - 'fade-in': 'fade-in .3s ease-in-out' + 'fade-in': 'fade-in .3s ease-in-out', + 'wewew': 'wewew .45s ease-in-out', } }, },