UNPKG

leumas-private-shared

Version:

Private React JSX Package For Leumas Shared Components, Headers, Footers, Asides, Login Pages, API Key Manager and much more. Styles and everything reusable to avoid DRY code across all of our subdomains

239 lines (199 loc) 9.1 kB
import React, { useState, useEffect } from 'react'; import {LeumasBaseStyle} from "../../styles/baseStyles" import { FaPlay, FaVideo, FaCode, FaInfoCircle } from 'react-icons/fa'; import { MdHome } from 'react-icons/md'; import axios from "axios" import Spinner2 from '../Loaders/Spinner2'; import { getItemById } from '../../helpers/LMS-WildCard-Helpers/UniversalCrud/UniversalCrudHelpers'; import { useAuthUser } from 'react-auth-kit'; import {sendIRSignalToPort} from "../../components/NPMDev/SerialPort/sendIRSignalToPort" const ButtonCard = ({ buttonData , selectedPort}) => { const [isModalOpen, setModalOpen] = useState(false); const [isLoading, setIsLoading] = useState(false); const [modalContent, setModalContent] = useState(''); const auth = useAuthUser(); console.log("buttonData" , buttonData) const handleButtonClick = (type) => { switch(type) { case 'audioBtn': playAudio(buttonData.audioUrl); break; case 'videoBtn': playVideo(buttonData.videoUrl); break; case 'smartHomeBtn': controlSmartHomeDevice(buttonData.smartHomeDeviceId); break; case 'gptBtn': runGPTCommand(buttonData.gptCommand); break; case 'actionBtn': triggerServerAction(buttonData.serverAction); break; case 'codeBtn': executeCode(buttonData.code); break; case 'IrBtn': triggerIRSignal(buttonData.irSignalData , selectedPort); break; default: console.warn("Unknown button type"); } } const playAudio = (audioUrl) => { // Create a new audio object const audio = new Audio(audioUrl); // Event listener for when the audio has ended audio.addEventListener("ended", () => { console.log(`Finished playing audio from ${audioUrl}`); }); // Play the audio audio.play().catch(error => { console.error(`Failed to play audio from ${audioUrl}`, error); }); }; const playVideo = (videoUrl) => { // Create a video element const video = document.createElement("video"); video.setAttribute("controls", ""); // Add video controls video.src = videoUrl; // Create an overlay for the video to be center-aligned const overlay = document.createElement("div"); overlay.style.position = "fixed"; overlay.style.top = "0"; overlay.style.right = "0"; overlay.style.bottom = "0"; overlay.style.left = "0"; overlay.style.background = "rgba(0,0,0,0.8)"; overlay.style.display = "flex"; overlay.style.alignItems = "center"; overlay.style.justifyContent = "center"; overlay.style.zIndex = "1000"; // to ensure it's on top of other elements // Append video to overlay overlay.appendChild(video); // Append overlay to the body document.body.appendChild(overlay); // Play the video video.play().catch(error => { console.error(`Failed to play video from ${videoUrl}`, error); }); // Remove the video overlay when video ends video.addEventListener("ended", () => { document.body.removeChild(overlay); }); // Optionally, click outside of the video or on the video to close it overlay.addEventListener("click", () => { video.pause(); document.body.removeChild(overlay); }); }; const controlSmartHomeDevice = (deviceId) => { // Logic to control smart home device console.log(`Controlling device with ID ${deviceId}`); } const runGPTCommand = async (gptCommand) => { setIsLoading(true); // Logic to run GPT command console.log(`Running GPT command: ${gptCommand}`); const messages = [ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": gptCommand } ]; try { const res = await axios.post(`${import.meta.env.VITE_REACT_APP_LEUMAS_AI_ENDPOINT}/openai/chatgpt/chat-completions/chat-completion`, { model: "gpt-3.5-turbo", messages: messages }); if (res.data.choices && res.data.choices[0] && res.data.choices[0].message) { setModalContent(res.data.choices[0].message.content); setModalOpen(true); } } catch (error) { console.error('Error making request to backend:', error); setModalContent('Error fetching response from GPT-3.'); setModalOpen(true); } finally { setIsLoading(false) } } const triggerServerAction = (serverAction) => { // Logic to trigger a server action console.log(`Triggering server action: ${serverAction}`); } const executeCode = (code) => { // Logic to execute the provided code // Be VERY cautious executing arbitrary code for security reasons console.log(`Executing code: ${code}`); } const triggerIRSignal = async (irSignalData , selectedPort) => { if (!selectedPort) { console.error("No port selected!"); return; } getItemById("IRSignal", irSignalData, "LeumasAPI", auth()?.token).then(async (data) => { console.log(data); if (data && data.IRValue && selectedPort) { // ensure you have the data and a selected port const response = await sendIRSignalToPort(selectedPort, data.IRValue); if (response && response.success) { console.log(response.message); } else { console.error("Failed to send IR signal"); } } }); } const getIconForButtonType = (type) => { switch(type) { case 'audioBtn': return <FaPlay size={24} />; // Adjust size as necessary case 'videoBtn': return <FaVideo size={24} />; case 'codeBtn': return <FaCode size={24} />; case 'smartHomeBtn': return <MdHome size={24} />; case 'actionBtn' : return <MdHome size={24} />; case 'gptBtn' : return <MdHome size={24} />; case 'IrBtn' : return <MdHome size={24} />; // ... add other cases for other button types default: return null; } }; return ( <> {isLoading ? <Spinner2 loading={true} /> : <div className={`${LeumasBaseStyle} max-w-[100px] max-h-[100px] min-h-[100px] relative group hover:shadow-xl hover:scale-110 border-glow`} data-tooltip={buttonData.description || "Some default tooltip text"}> <button className="w-full h-full relative" onClick={() => handleButtonClick(buttonData.buttonType)}> <span className="absolute bottom-0 right-0 text-xs "> {buttonData.buttonType} </span> <div className="absolute inset-0 flex items-center justify-center"> {getIconForButtonType(buttonData.buttonType)} </div> </button> <button className="absolute bottom-0 left-0 text-xs p-1 bg-white bg-opacity-50 rounded-full hover:bg-opacity-100 transition-opacity duration-300" onClick={() => { /* Handle the 'view details' logic here */ }}> <FaInfoCircle /> </button> {/* Tooltip styling */} <div className="absolute bottom-full left-1/2 transform -translate-x-1/2 translate-y-2 px-2 py-1 bg-black text-white text-xs rounded shadow-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none"> {buttonData.description} </div> {/* <div className='absolute top-0 right-0 w-full text-[8px] max-w-[50px]'> <SerialPortSelector setSelectedPort={handlePortChange} /> </div> */} </div> } {isModalOpen && ( <div className=" p-6 rounded shadow-lg absolute bottom-0 left-0 max-w-sm bg-transparent z-50 bg-white text-black m-4 max-h-[250px] max-w-[400px] "> <button onClick={() => setModalOpen(false)} className="absolute top-2 right-2">X</button> <p>{modalContent}</p> </div> )} </> ); } export default ButtonCard;