Skip to content

Instantly share code, notes, and snippets.

@adrianhajdin
Created March 31, 2023 12:33
Show Gist options
  • Save adrianhajdin/597252d9d77fa65e30f596d99b03cc11 to your computer and use it in GitHub Desktop.
Save adrianhajdin/597252d9d77fa65e30f596d99b03cc11 to your computer and use it in GitHub Desktop.
Build and Deploy an AI-Powered 3D Website Using React | 2023 Three JS Course Tutorial for Beginners
{/* Download button */}
<button className='download-btn' onClick={downloadCanvasToImage}>
<img
src={download}
alt='download_image'
className='w-3/5 h-3/5 object-contain'
/>
</button>
@import url("https://fonts.googleapis.com/css2?family=Nunito+Sans:ital,wght@0,200;0,600;1,900&display=swap");
@import url("https://rsms.me/inter/inter.css");
@tailwind base;
@tailwind components;
@tailwind utilities;
html {
font-family: "Inter", sans-serif;
}
@supports (font-variation-settings: normal) {
html {
font-family: "Inter var", sans-serif;
}
}
.app {
@apply relative w-full h-screen overflow-hidden;
}
.home {
@apply w-fit xl:h-full flex xl:justify-between justify-start items-start flex-col xl:py-8 xl:px-36 sm:p-8 p-6 max-xl:gap-7 absolute z-10;
}
.home-content {
@apply flex-1 xl:justify-center justify-start flex flex-col gap-10;
}
.head-text {
@apply xl:text-[10rem] text-[6rem] xl:leading-[11rem] leading-[7rem] font-black text-black;
}
.download-btn {
@apply w-14 h-14 flex justify-center items-center rounded-full glassmorphism cursor-pointer outline-none;
}
.editortabs-container {
@apply glassmorphism w-16 border-[2px] rounded-lg flex flex-col justify-center items-center ml-1 py-4 gap-4;
}
.filtertabs-container {
@apply absolute z-10 bottom-5 right-0 left-0 w-full flex justify-center items-center flex-wrap gap-4;
}
.aipicker-container {
@apply absolute left-full ml-3 glassmorphism p-3 w-[195px] h-[220px] rounded-md flex flex-col gap-4;
}
.aipicker-textarea {
@apply w-full bg-transparent text-sm border border-gray-300 p-2 outline-none flex-1;
}
.filepicker-container {
@apply absolute left-full ml-3 glassmorphism p-3 w-[195px] h-[220px] flex flex-col rounded-md;
}
.filepicker-label {
@apply border border-gray-300 py-1.5 px-2 rounded-md shadow-sm text-xs text-gray-700 focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 cursor-pointer w-fit;
}
.tab-btn {
@apply w-14 h-14 flex justify-center items-center cursor-pointer select-none;
}
.glassmorphism {
background: rgba(255, 255, 255, 0.25);
box-shadow: 0 2px 30px 0 rgba(31, 38, 135, 0.07);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
border: 1px solid rgba(255, 255, 255, 0.18);
}
input[type="file"] {
z-index: -1;
position: absolute;
opacity: 0;
}
.sketch-picker {
width: 170px !important;
background: rgba(255, 255, 255, 0.25) !important;
box-shadow: 0 2px 30px 0 rgba(31, 38, 135, 0.07) !important;
backdrop-filter: blur(4px) !important;
-webkit-backdrop-filter: blur(4px) !important;
border: 1px solid rgba(255, 255, 255, 0.18) !important;
border-radius: 6px !important;
}
.sketch-picker > div:nth-child(3) {
display: none !important;
}
@Parthmudgal15105
Copy link

Hey guys I'm getting this error image The page works and then I get this errors within a second.

Can someone help me out with this

@GIT-Gizmo
Copy link

Hey guys I'm getting this error image The page works and then I get this errors within a second.
Can someone help me out with this

I fixed it by commenting out the map-anisotropy={16} property in the Shirt.jsx component.

@GIT-Gizmo
Copy link

Why when AI Picker not load image? when Click Ask AI button this error messege pop up TypeError: Failed to fetch
This error Messege display in Console POST http://localhost:8080/api/v1/dalle net::ERR_CONNECTION_REFUSED handleSubmit @ Customizer.jsx:68 handleClick @ AIPicker.jsx:36 callCallback2 @ chunk-ZK6T5TI4.js?v=e6e1dfba:3674 invokeGuardedCallbackDev @ chunk-ZK6T5TI4.js?v=e6e1dfba:3699 invokeGuardedCallback @ chunk-ZK6T5TI4.js?v=e6e1dfba:3733 invokeGuardedCallbackAndCatchFirstError @ chunk-ZK6T5TI4.js?v=e6e1dfba:3736 executeDispatch @ chunk-ZK6T5TI4.js?v=e6e1dfba:7016 processDispatchQueueItemsInOrder @ chunk-ZK6T5TI4.js?v=e6e1dfba:7036 processDispatchQueue @ chunk-ZK6T5TI4.js?v=e6e1dfba:7045 dispatchEventsForPlugins @ chunk-ZK6T5TI4.js?v=e6e1dfba:7053 (anonymous) @ chunk-ZK6T5TI4.js?v=e6e1dfba:7177 batchedUpdates$1 @ chunk-ZK6T5TI4.js?v=e6e1dfba:18909 batchedUpdates @ chunk-ZK6T5TI4.js?v=e6e1dfba:3579 dispatchEventForPluginEventSystem @ chunk-ZK6T5TI4.js?v=e6e1dfba:7176 dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ chunk-ZK6T5TI4.js?v=e6e1dfba:5478 dispatchEvent @ chunk-ZK6T5TI4.js?v=e6e1dfba:5472 dispatchDiscreteEvent @ chunk-ZK6T5TI4.js?v=e6e1dfba:5449
This is My Customizer.jsx


`import React, { useState, useEffect } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import { useSnapshot } from 'valtio';

import config from '../config/config';
import state from '../store';
import { download } from '../assets';
import { downloadCanvasToImage, reader } from '../config/helpers';
import { EditorTabs, FilterTabs, DecalTypes } from '../config/constants';
import { fadeAnimation, slideAnimation } from '../config/motion';
import { AIPicker, ColorPicker, CustomButton, FilePicker, Tab } from '../components';

const Customizer = () => {
  const snap = useSnapshot(state);

  const [file, setFile] = useState('');

  const [prompt, setPrompt] = useState('');
  const [generatingImg, setGeneratingImg] = useState(false);

  const [activeEditorTab, setActiveEditorTab] = useState("");
  const [activeFilterTab, setActiveFilterTab] = useState({
    logoShirt: true,
    stylishShirt: false,
  })

  // show tab content depending on the activeTab
  const generateTabContent = () => {
    switch (activeEditorTab) {
      case "colorpicker":
        return <ColorPicker />
      case "filepicker":
        return <FilePicker
          file={file}
          setFile={setFile}
          readFile={readFile}
        />
      case "aipicker":
        return <AIPicker 
          prompt={prompt}
          setPrompt={setPrompt}
          generatingImg={generatingImg}
          handleSubmit={handleSubmit}
        />
      default:
        return null;
    }
  }

  const handleSubmit = async (type) => {
    if(!prompt) return alert("Please enter a prompt");

    try {
      setGeneratingImg(true);

      const response = await fetch('http://localhost:8080/api/v1/dalle', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          prompt,
        })
      })


      const data = await response.json();

      handleDecals(type, `data:image/png;base64,${data.photo}`)
    } catch (error) {
      alert(error)
    } finally {
      setGeneratingImg(false);
      setActiveEditorTab("");
    }
  }

  const handleDecals = (type, result) => {
    const decalType = DecalTypes[type];

    state[decalType.stateProperty] = result;

    if(!activeFilterTab[decalType.filterTab]) {
      handleActiveFilterTab(decalType.filterTab)
    }
  }

  const handleActiveFilterTab = (tabName) => {
    switch (tabName) {
      case "logoShirt":
          state.isLogoTexture = !activeFilterTab[tabName];
        break;
      case "stylishShirt":
          state.isFullTexture = !activeFilterTab[tabName];
        break;
      default:
        state.isLogoTexture = true;
        state.isFullTexture = false;
        break;
    }

    // after setting the state, activeFilterTab is updated

    setActiveFilterTab((prevState) => {
      return {
        ...prevState,
        [tabName]: !prevState[tabName]
      }
    })
  }

  const readFile = (type) => {
    reader(file)
      .then((result) => {
        handleDecals(type, result);
        setActiveEditorTab("");
      })
  }

  return (
    <AnimatePresence>
      {!snap.intro && (
        <>
          <motion.div
            key="custom"
            className="absolute top-0 left-0 z-10"
            {...slideAnimation('left')}
          >
            <div className="flex items-center min-h-screen">
              <div className="editortabs-container tabs">
                {EditorTabs.map((tab) => (
                  <Tab 
                    key={tab.name}
                    tab={tab}
                    handleClick={() => setActiveEditorTab(tab.name)}
                  />
                ))}

                {generateTabContent()}
              </div>
            </div>
          </motion.div>

          <motion.div
            className="absolute z-10 top-5 right-5"
            {...fadeAnimation}
          >
            <CustomButton 
              type="filled"
              title="Go Back"
              handleClick={() => state.intro = true}
              customStyles="w-fit px-4 py-2.5 font-bold text-sm"
            />
          </motion.div>

          <motion.div
            className='filtertabs-container'
            {...slideAnimation("up")}
          >
            {FilterTabs.map((tab) => (
              <Tab
                key={tab.name}
                tab={tab}
                isFilterTab
                isActiveTab={activeFilterTab[tab.name]}
                handleClick={() => handleActiveFilterTab(tab.name)}
              />
            ))}
          </motion.div>
        </>
      )}
    </AnimatePresence>
  )
}

export default Customizer`

Can someone Help me???

Did you manage to fix it? I'm facing the same issue: When trying to generate an Image AI (My code looks the same as in the tutorial) image

Hi, can you resolve this?

Am facing such problem, were you able to sort it out sir

For everyone experiencing the AI Image generation issue, I found an alternative by using another AI from rapidapi, all you have to do is register on rapidapi.com and subscribe to this api that gives 20 free image generation per month https://rapidapi.com/bussinesonline250/api/ai-text-to-image-generator-api after registering go here to copy the backend code to use the api to generate image.

@marvelfriction
Copy link

const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY // This is also the default, can be omitted
});

Thanks this was indeed helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment