wahanegi/vibereport

View on GitHub
app/javascript/components/Pages/MemeSelection.js

Summary

Maintainability
B
4 hrs
Test Coverage
import React, {useEffect, useState, useRef} from "react"
import {useNavigate} from "react-router-dom";
import Gif from "./Gifs";
import {
  BigBtnEmotion,
  BtnOutline,
  BtnPrimary,
  Header,
  Wrapper
} from "../UI/ShareContent";
import {backHandling, gifUrlWithId, isBlank, isPresent} from "../helpers/helpers";
import CornerElements from "../UI/CornerElements";

export const getAndSetImageHeight = (file, setImageHeight, callback) => {
  const img = new Image();
  img.src = URL.createObjectURL(file);
  img.onload = () => {
    setImageHeight(img.naturalHeight);
    callback(true)
  };
};

const MemeSelection = ({data, setData, saveDataToDb, steps, service, isCustomGif, setIsCustomGif, draft}) => {
  const {emotion, api_giphy_key, response} = data
  const navigate = useNavigate()
  const {isLoading, error} = service
  const [gifUrl, setGifUrl] = useState(response.attributes.gif || {})
  const [selectedGifIndex, setSelectedGifIndex] = useState(null);
  const [uploading, setUploading] = useState(false);
  const [uploadingError, setUploadingError] = useState('');
  const [isDraft, setIsDraft] = useState(draft);
  const [selectedFile, setSelectedFile] = useState(null);
  const fileInputRef = useRef(null);
  const [imageHeight, setImageHeight] = useState(null);

  const handleFileChange = (event) => {
    const file = event.target.files[0];
    if (!file) return;

    if (file.size <= 100 * 1024 * 1024) { // 100 MB in bytes
      if (file.type === 'image/gif' || file.type.startsWith('video/')) {
        const callback = (success) => {
          if (success) setSelectedFile(file)
        }
        getAndSetImageHeight(file, setImageHeight, callback)
      } else {
        setSelectedFile(null);
        alert('Please select a GIF or Video file.');
      }
    } else {
      setSelectedFile(null);
      alert('File size exceeds the limit of 100 MB.');
    }
  };

  const handleButtonClick = () => {
    if (fileInputRef.current) {
      fileInputRef.current.click();
    }
  };

  const handleSaveDraft = () => {
    const dataDraft = {gif: gifUrl, draft: true}
    saveDataToDb(steps, dataDraft);
    setIsDraft(true)
  }

  useEffect(() => {
    if (gifUrl !== response.attributes.gif && isDraft) {
      setIsDraft(false);
    }
  }, [gifUrl]);

  const handlingOnClickSkip = () =>{
    steps.push('emotion-intensity')
    saveDataToDb( steps , { gif: null, draft: false })
  }

  const chooseGIPHYHandling = () => {
    steps.push('emotion-intensity');
    saveDataToDb(steps, { gif: gifUrl, draft: false });
  }

  const uploadGIPHYHandling = async () => {
    setUploading(true)
    setUploadingError('')
    const formData = new FormData();
    formData.append('file', selectedFile);
    formData.append('api_key', api_giphy_key);
    // formData.append('username', 'Vibereport');

    try {
      const response = await fetch('https://upload.giphy.com/v1/gifs', {
        method: 'POST',
        body: formData,
      });
      const responseData = await response.json();
      setGifUrl({src: gifUrlWithId(responseData.data.id), height: imageHeight * 0.22})
      setIsCustomGif(true)
      setSelectedFile(null)
      setUploading(false)
    } catch (error) {
      setSelectedFile(null)
      setUploading(false)
      setUploadingError(error.message)
    }
  };

  useEffect(()=> {
    navigate(`/${data.response.attributes.steps.slice(-1).toString()}`);
  },[])

  useEffect(()=> {
    selectedFile && uploadGIPHYHandling();
  },[selectedFile])


  const Navigation = () =>
    <div className='d-flex justify-content-between gap-3 pb-45'>
      <div>
        <h5 className='mt-2 mb-0 text-muted'>Share it in your way!</h5>
        <div>
          <BtnOutline text='Upload your own meme!' onClick={handleButtonClick} />
          <input
            type="file"
            accept="image/gif, video/*" // Accepts GIF and any video format
            ref={fileInputRef}
            style={{ display: 'none' }}
            onChange={handleFileChange}
          />
        </div>
      </div>
      <div style={{marginTop: 52}}>
        <BtnPrimary text='Next' onClick={chooseGIPHYHandling} hidden={isBlank(gifUrl)} />
        <BtnPrimary text='Skip' onClick={handlingOnClickSkip} hidden={isPresent(gifUrl)} />
      </div>
    </div>

  const Header = () => <div className='d-flex justify-content-between mx-3 mt-8'>
    <div className='mx-auto' >
      <h5 style={{opacity: 0.6}}>You picked:</h5>
      <BigBtnEmotion emotion={emotion} onClick={backHandling} />
    </div>
  </div>

  if (!!error) return <p>{error.message}</p>

  return !isLoading && <Wrapper>
    <Header />
    <div className='align-self-center gif-wrap'>
        <Gif {...{emotion, api_giphy_key, gifUrl, setGifUrl, selectedGifIndex,
                  setSelectedGifIndex, isCustomGif, setIsCustomGif, uploading,
                  uploadingError}} />
      <Navigation />
    </div>
    <CornerElements data = { data }
                    setData = { setData }
                    saveDataToDb={saveDataToDb}
                    steps={steps}
                    draft={isDraft}
                    handleSaveDraft={handleSaveDraft} />
  </Wrapper>
}

export default MemeSelection;