Skip to content

A new react project, this will be a Clone of the cargurus.com

Notifications You must be signed in to change notification settings

aytacg26/cargurusClone

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A React Project (Clone of www.cargurus.com)

This will be a complete MERN project and will be the clone of cargurus.com current sturcture contains half of home page with drop downs and different types of search forms. All images are from cargurus.com, after completion of react part a backend will be prepared with the help of Nodejs, Express and MongoDB

Json file added for all brands, models of brands and logos of brands inside BrandsModelsJSON folder, this will be used for MongoDB brands collection

Facebook Style Expanding TextArea created : TextArea automatically expands and shrinks vertically, no scroll required, also with maxLength, optional remaining char size counter added, which shows how many more characters remain to write message (something similar to Twitter)

Completed Parts: (Without any state management - Redux will be used...)

  • Nav
  • Home Page
  • Used Cars Page
  • Product/#id page (No car image, will be added after completion of New Car Form and Backend for image upload)
let rowAdded = [{ count: 0, charSize: 0 }]; //This one used outside of function, instead of as state, state version tried but creates problems because of state update
                                            //latecy.
const TextArea = ({
  onChange,
  placeholder,
  name,
  title,
  label,
  value,
  maxLength,
  counterText,
  showCounter,
  warningMessage,
  notValid,
  useTextError,
  onBlur,
}) => {
  const [rowSize, setRowSize] = useState(4);
  const [currentScrollHeight, setCurrentScrollHeight] = useState(null);
  const [counter, setCounter] = useState(0);
  const [counterInit, setCounterInit] = useState(0);
  const [initScrollHeight, setInitScrollHeight] = useState(null);
  const textAreaRef = useRef();

  useEffect(() => {
    //Both are same but, one changes in every expand of textarea, the other one remains same for the end of shrink process
    setCurrentScrollHeight(textAreaRef.current.scrollHeight);
    setInitScrollHeight(textAreaRef.current.scrollHeight);
  }, []);

  useEffect(() => {
    const countValue = maxLength || 500;
    setCounter(countValue);
    setCounterInit(countValue);
  }, [maxLength]);

  const handleChange = (e) => {
    onChange && onChange(e);

    setCounter((prevState) => {
      if (counterInit - prevState > e.target.value.length) {
        return prevState + 1;
      } else {
        return prevState - 1;
      }
    });

    if (e.target.scrollHeight > currentScrollHeight) {
      setRowSize((prevState) => prevState + 1);
      setCurrentScrollHeight(e.target.scrollHeight);
      //convert to number array and use push method to add new charSize
      rowAdded = [
        ...rowAdded,
        {
          count: rowAdded[rowAdded.length - 1].count + 1, //not required, unnecessary calculation and copy process.
          charSize: e.target.value.length,
        },
      ];
    }

    //instead of rowAdded[rowAdded.length-1].charSize, use  rowAdded[rowAdded.length-1]
    if (
      rowAdded.length > 0 &&
      e.target.value.length < rowAdded[rowAdded.length - 1].charSize
    ) {
      setRowSize((prevState) => prevState - 1);
      rowAdded.pop();

      if (rowAdded.length === 1) {
        setCurrentScrollHeight(initScrollHeight);
      }
    }

    //prevent unnecessary space at the beginning of message and also in case of select&delete by the help
    //of mouse & backspace, it will set counter to maxLength
    if (textAreaRef.current.value.trim() === '') {
      setCounter(maxLength || 500);
      textAreaRef.current.value = '';
    }
  };

  const textClass = `${classes.TextArea} ${notValid ? classes.NotValid : ''}`;
  const warningClass = `${classes.WarningContainer} ${
    notValid ? classes.Show : ''
  }`;

  return (
    <label className={classes.textareaLabel}>
      {/* <span>Label</span>  This part should work like in Input Component*/}
      <textarea
        rows={rowSize}
        cols='50'
        placeholder={placeholder}
        name={name}
        title={title}
        maxLength={counterInit}
        value={value}
        className={textClass}
        onChange={handleChange}
        onBlur={onBlur}
        ref={textAreaRef}
        style={{ marginBottom: !showCounter ? '15px' : '' }}
      ></textarea>
      <span
        className={`${classes.Label} ${value ? classes.filled : ''} ${
          notValid ? classes.NotValid : ''
        }`}
      >
        {label}
      </span>
      {warningMessage && !useTextError && (
        <div className={warningClass}>
          <span className={classes.Triangle}></span>
          <div className={classes.Warning}>{warningMessage}</div>
        </div>
      )}
      {showCounter && (
        <div
          className={`${classes.remainingAmount} ${
            notValid ? classes.NotValid : ''
          }`}
        >
          <span className={classes.CounterText}>
            {counterText || 'Remaining : '}
          </span>
          <span className={classes.MaxLength}>{counter}</span>
        </div>
      )}
      {useTextError && notValid && (
        <span className={classes.TextError}>{warningMessage}</span>
      )}
    </label>
  );
};

export default TextArea;

About

A new react project, this will be a Clone of the cargurus.com

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published