2
\$\begingroup\$

I build project Case opening simulator in React JS + tailwind. I am looking for maybe another way to implement the structure of code and tell me if I've done something wrong, what I should do better or to add something more.

   import React, { useState, useEffect } from 'react';
import ResultDisplay from './ResultDisplay';
import MenuButton from './MenuButton';
import Instructions from './Instructions';
import Controls from './Controls';
import { calculateResponsiveSizes } from './ResponsiveUtils';


const CaseOpener = () => {
  const itemsAmount = 100;
  const [ItemsList, setItemsList] = useState([]);
  const [elementWidth, setElementWidth] = useState(200);
  const [reelContainerWidth, setReelContainerWidth] = useState(1000);
  const [winningItem, setWinningItem] = useState(null);
  const [reelItems, setReelItems] = useState([]);
  const [isOpening, setIsOpening] = useState(false);
  const [hasOpened, setHasOpened] = useState(false);
  const [selectedCase, setselectedCase] = useState(null);
  const [randomSpin, setRandomSpin] = useState(0);
  const spinDuration = 10;
  const minSpin = -13000;
  const maxSpin = -12050;
  const baseRandomSpin = Math.floor(Math.random() * (maxSpin - minSpin + 1)) + minSpin;
//  loading skin data


   const goToCase = () => {
    setselectedCase(true);
  };

  

// window size change chandler
useEffect(() => {
  const handleResize = () => {
    if (!isOpening) { // tylko gdy nie jest w trakcie otwierania
      calculateResponsiveSizes(setElementWidth, setReelContainerWidth, setRandomSpin, baseRandomSpin);
    }
  };
  handleResize();
  window.addEventListener('resize', handleResize);
  return () => window.removeEventListener('resize', handleResize);
}, [isOpening, baseRandomSpin]);



const openCase = async () => {
  setIsOpening(true);
  setHasOpened(false);
  const baseElementWidth = 200;
  const newRandomSpin = (baseRandomSpin * elementWidth) / baseElementWidth;
  setRandomSpin(newRandomSpin);
  try {
    const response = await fetch('http://localhost:5000/open-case-batch');
    const data = await response.json();
    setItemsList(data);
    console.log("Wylosowane przedmioty:", data);
    
    const generatedItems = [];
    for(let i = 0; i < itemsAmount; i++) {
      generatedItems.push(data[i]);
    }
    setReelItems(generatedItems);
    
    console.log("-----\\\\\\\\\\\\\\\\\\\\\\\\\\-----");
    const OFFSET_ELEMENTS = -2;
    const OFFSET_PX = OFFSET_ELEMENTS * elementWidth;

    // calc index of winning item
    const index = Math.floor((-newRandomSpin - OFFSET_PX + elementWidth / 2) / elementWidth);

    console.log("randomSpin:", randomSpin);
    console.log("elementWidth:", elementWidth);
    console.log("winning index:", index);
    setWinningItem(generatedItems[index]);
    console.log("winning item: ", generatedItems[index]?.skin_name); // Changed from 'name' to 'skin_name'
    console.log("Posibble floats: ",generatedItems[index].float_min," - ",(generatedItems[index].float_max));
    console.log("Skin float: ",generatedItems[index].float);
    console.log(generatedItems[index].condition);

   // console.log(winningItem);

    setTimeout(() => {
      setIsOpening(false);
      setHasOpened(true);
    }, spinDuration * 1000);

  } catch (error) {
    console.error("Błąd podczas pobierania przedmiotów:", error);
    setIsOpening(false);
  }
};
  //delete
const Calculator = () => {
  useEffect(() => {
    const calculate = async () => {
      try {
        const response = await fetch('http://localhost:5000/calculate');
        const data = await response.json();
        console.log('Wynik z backendu:', data);
      } catch (error) {
        console.error('error loading file:', error);
      }
    };

    calculate();
  }, []);

  return null; // nic nie renderuje
};
  const resetCase = () => {
    setIsOpening(false);
    setHasOpened(false);
    setReelItems([]);
  };

  const generateReel = () => {
    if (reelItems.length === 0) {
      return [];
    }

    const items = [];
    for (let i = 0; i < reelItems.length; i++) {
      const item = reelItems[i];

      items.push(
        <div
          key={i}
          className="flex-shrink-0 bg-gradient-to-br from-gray-600 to-[#4a90e2] rounded-lg
          border border-gray-700 flex items-center justify-center shadow-lg"
          style={{ 
            width: `${elementWidth}px`,
            height: `${elementWidth * 0.8}px`
          }}
        > 
          <img
            src={item.image_url}
            alt={item.skin_name}
            className="object-cover rounded-md"
            style={{
              width: `${elementWidth * 0.7}px`,
              height: `${elementWidth * 0.56}px`
            }}
          /> 
        </div>
      );
    }
    return items;
  };

  return (
    <>
      <div className="h-20 flex items-center relative overflow-hidden bg-[#26262B] justify-center">
        <div className="hidden sm:flex">
          <MenuButton>Menu</MenuButton>
          <MenuButton>Daily bonus</MenuButton>
          <MenuButton>Contracts</MenuButton>
          <MenuButton>Market</MenuButton>
          <MenuButton>Inventory</MenuButton>
        </div>
        <div className="sm:hidden">
          <MenuButton>☰</MenuButton>
        </div>
      </div>

      <div className="min-h-[calc(100vh-5rem)] flex items-center justify-center
      relative overflow-hidden bg-[#1a1a1a] border-t border-black px-4">
        <div className="bg-[#2a2a2a] rounded-2xl shadow-2xl p-4 sm:p-8 lg:p-16 w-full max-w-7xl
        border-2 border-[#1a1a2a]">

          <h1 className="text-2xl sm:text-3xl lg:text-4xl font-bold text-center mb-8 text-[#f8f9fa]">
            Case Opening
          </h1>

          {!selectedCase && (
            <div className="mb-8 text-center">
              <label className="inline-block bg-[#f39c12]
              hover:bg-[#e67e22] text-white font-bold py-3 px-6 rounded-lg cursor-pointer transition-colors duration-200
              border-2 border-[#f39c12]
              transform hover:scale-105" onClick={goToCase}
              >
                Select this case
              </label>
            </div>
          )}

          {/* Case Opening Area */}
          {selectedCase && (
            <div className="mb-8">
              {/* Reel Container */}
              <div className="relative bg-[#333333] rounded-xl p-4 sm:p-8 lg:p-16 mb-6 overflow-hidden flex justify-center">
                {/* Selection Line */}
                <div 
                  id='marker' 
                  className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-0.5 bg-[#4a90e2] z-10 shadow-lg"
                  style={{ height: `${elementWidth * 0.8}px` }}
                ></div>
                
                {/* Reel */}
                <div 
                  id='koniec' 
                  style={{ width: `${elementWidth * 5}px`,height: `${elementWidth * 0.8}px` }} 
                  className="relative overflow-hidden"
                >
                  <div
                    className={`flex ${isOpening ? 'animate-spin-reel' : ''}`}
                  >
                    {generateReel()}
                  </div>
                </div>
              </div>

              <Controls
                onOpen={openCase}
                onReset={resetCase}
                onChangeImage={() => setselectedCase(null)}
                isOpening={isOpening}
              />

              <ResultDisplay hasOpened={hasOpened} winningItem={winningItem}></ResultDisplay>
            </div>
          )}

        <Instructions selectedCase={selectedCase} />

        </div>

        <style jsx>{`
          @keyframes spin-reel {
            0%   { transform: translateX(0px); }
            100% { transform: translateX(${randomSpin}px); }
          }

         .animate-spin-reel {
  animation: spin-reel 9.5s cubic-bezier(0.33, 1, 0.68, 1) forwards; 
}
        `}</style>
      </div>
    </>
  );
};

export default CaseOpener;

ResponsiveUtils.jsx:

export const calculateResponsiveSizes = (
  setElementWidth,
  setReelContainerWidth,
  setRandomSpin,
  baseRandomSpin
) => {
  const screenWidth = window.innerWidth;

  let newElementWidth;
  let newContainerWidth;

  if (screenWidth < 640) {
    newElementWidth = 120;
    newContainerWidth = screenWidth * 0.8;
  } else if (screenWidth < 1024) {
    console.log("tablet");
    newElementWidth = 150;
    newContainerWidth = screenWidth * 0.7;
  } else if (screenWidth < 1296) {
    console.log("pc small screen");
    newElementWidth = 170;
    newContainerWidth = screenWidth * 0.7;
  } else {
    console.log("pc");
    newElementWidth = 200;
    newContainerWidth = 1000;
  }

  setElementWidth(newElementWidth);
  setReelContainerWidth(newContainerWidth);

  const baseElementWidth = 200;
  const newRandomSpin = (baseRandomSpin * newElementWidth) / baseElementWidth;
  setRandomSpin(newRandomSpin);
};

\$\endgroup\$
1
  • \$\begingroup\$ I think it should be possible to make the game responsive entirely in CSS. \$\endgroup\$ Commented Jul 22 at 10:39

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.