영화 한줄평 프로젝트 빨안쓰 -1-

걍걍규·2023년 11월 3일
0
post-thumbnail

팝코넥트 소스코드
https://github.com/ganggyunggyu/Popcennet
빨안스 소스코드
https://github.com/ganggyunggyu/ReactMovieReviewApp

영화를 좋아해

영화도 좋아하고 남의 평을 보는것도 좋아한다 하지만 평을 남기기 부담스럽다
보다 영화에 집중한 사이트를 만들어보면 어떨까 라는 생각에 시작되었다

시작 !

사실 첫번째 프로젝트가 있었는데

PC

Mobile

SignUp

사장된 나의 프로젝트 .. 이쁘긴한데 나중에 보자

라프텔이라는 OTT사이트를 참고하여 작업했고

이 프로젝트의 목적은 AWS의 S3버킷을 이용하여 동영상을 최적화 해보는 것에 목적이 있었으나
나의 학습능력 부족과 팀과제 수행으로 인해 일단 밀리게 되었고

WebIDE 프로젝트가 끝난 이후에 바로 지금의 이동진 게섯거라 (부제 : 빨간안경쓰고) 프로젝트를 시작하게 되었다


여기부터가 빨안쓰 내용

메인 페이지

나는 깔끔한 디자인을 좋아한다 그리고 디자인이 잘 설계되어있는 웹과 앱을 보면 감탄하곤 한다
그러나 스스로 만드는 능력은 떨어진다 그럴라면 디자이너했지

그래서 세줄독후감 이라는 사이트를 많이 참고하여 디자인을 만들었고
혼자 하는 프로젝트였기에 Figma는 작성하지 않았다

헤더에서 로그인과 회원가입 메인페이지로 이동이 가능하며 반응형으로 모바일에선 보시다시피 상단바가 좌우 끝에 위치하게 된다

최근 리뷰가 남겨진 작품의 탭에서는 작품정보로 이동할 수 있다
로그인이 되어있으면 그 곳에서 평을 남길수 있고 로그인을 하지 않아도 타인의 평을 보는것은 가능하다

로그인 전

로그인 후

하단 우측에는 항상 같은 자리에 고정되어 있는 다크모드 버튼이 있다
다크모드일땐 #000이 완전 깜장색을 사용하지 않고 눈이 편안한 다크그레이 컬러를 적용하였다

다크모드 전

다크모드 후

회원가입

위에 말씀드린대로 깔끔한 디자인을 좋아한다
아주 심플하게 만들어보았다

구현된 것

  • 사용자의 입력을 받아 DB에 저장한다
  • 비밀번호 해싱

구현예정인 것

  • 이메일 중복확인
  • 이메일 , 비밀번호 , 전화번호 정규식 적용
  • 이메일 인증 or 폰인증
export const emailReg = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i;

export const passwordReg = /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,15}$/;
  • 정규식의 경우 별도의 util 폴더를 만들어 함수를 제작하여 사용할 예정이다
  • 중복확인은 DB를 순회하여 확인하면 될 것이라 생각하고 있다

위 두개의 경우는 팝코넥트에서 이미 해 둔것이 있음 그러나

  • 이메일 인증에 대해선 아직 정보가 없다 적용기를 포스팅할 예정

로그인

회원가입과 동일한 디자인이지 않은가?
이것은 모듈화의 기회이다

헤더 및 로고

import React from 'react';
import logo from '../imgs/glass.png';
export default function FormHeader({ text }) {
  return (
    <div>
      <img className="mx-auto h-10 w-auto" src={logo} alt="Your Company" />
      <h2 className="text-center text-2xl font-bold leading-9 tracking-tight">{text}</h2>
    </div>
  );
}

인풋박스

import React from 'react';

export default function FormInput({ value, setValue, type, placeholder, name }) {
  return (
    <div>
      <div className="mt-2 relative">
        {name === 'phoneNumber' ? (
          <input
            onChange={(e) => {
              setValue(
                e.target.value
                  .replace(/[^0-9]/g, '')
                  .replace(/^(\d{0,3})(\d{0,4})(\d{0,4})$/g, '$1-$2-$3')
                  .replace(/(\-{1,2})$/g, ''),
              );
            }}
            maxLength={13}
            value={value}
            type={type}
            placeholder={placeholder}
            required
            className="p-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-red-600 sm:text-sm sm:leading-6"
          />
        ) : (
          <input
            onChange={(e) => {
              setValue(e.target.value);
            }}
            value={value}
            type={type}
            placeholder={placeholder}
            required
            className="p-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-red-600 sm:text-sm sm:leading-6"
          />
        )}
        {name === 'email' ? (
          <button
            type="button"
            className="absolute top-1.5 right-3 text-white text-sm rounded-md bg-red-400 w-10 h-6 hover:bg-red-500"
          >
            인증
          </button>
        ) : (
          ''
        )}
        {/* {name === 'phoneNumber' ? <button>번호 인증</button> : ''} */}
      </div>
    </div>
  );
}

버튼

import React from 'react';

export default function FormButton({ submitFunc, text, isSubmitAble }) {
  return (
    <button
      onClick={submitFunc}
      type='button'
      // disabled={!isSubmitAble}
      className='flex w-full justify-center rounded-md bg-red-400 mt-3 p-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600'
    >
      {text}
    </button>
  );
}

상황에 맞는 함수와 텍스트를 보여줄수 있도록 props를 받는 컴포넌트를 만들어 두었다

로그인폼

import React, { useState } from 'react';
import FormHeader from '../components/FormHeader';
import FormInput from '../components/FormInput';
import FormButton from '../components/FormButton';

export default function Login() {

  const navigator = useNavigate();
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const FormItems = [
    { value: email, setValue: setEmail, type: 'email', placeholder: '이메일' },
    {
      value: password,
      setValue: setPassword,
      type: 'password',
      placeholder: '비밀번호',
    },
  ];


  return (
    <div className='flex flex-col h-screen justify-center items-center'>
      <FormHeader text={'로그인'} />
      <form className='w-5/6 md:w-80 mt-5'>
        {FormItems.map((el, i) => {
          return (
            <FormInput
              key={i}
              value={el.value}
              setValue={el.setValue}
              type={el.type}
              placeholder={el.placeholder}
            />
          );
        })}
        <FormButton submitFunc={isLogin} text={'로그인'} />
        <FormButton submitFunc={isJoin} text={'회원가입'} />
      </form>
    </div>
  );
}

이런식으로 사용해주었다 (불필요한 코드는 제거했음)

그 외

Card는 ?

팝코넥트 작업할때 만들어 놓은걸 사용하였다
빨안쓰에는 두가지의 카드가 존재하는데 ..

  1. 콘텐츠에 대한 정보를 담고있는 카드
  • 이 카드는 TMDB에서 가져온 콘텐츠에 대한 정보를 가지고 있다


마우스 올림

  1. 리뷰에 대한 정보를 담고있는 카드
  • 이 카드가 내 DB에 저장되어있는 정보이며 유저가 작성한 게시글이라고 이해하시면 편하다


마우스를 올려 한줄평을 미리 볼수 있드아

import React, { useState } from 'react';
import styled from './Card.module.css';

export default function CardReview({ content, onClick }) {
  const [cardHover, setCardHover] = useState(false);
  const cardMouseOver = () => {
    setCardHover(true);
  };
  return (
    <div
      onClick={onClick}
      onMouseOver={cardMouseOver}
      onMouseLeave={() => setCardHover(false)}
      className={`${styled.CardStyled}`}
    >
      {cardHover ? (
        <p className={`${styled.CardReview} absolute z-10 text-white p-1`}>{content.review}</p>
      ) : null}

      <div className={`w-64 h-80 text-center border shadow-md`}>
        <img className="w-full h-5/6" src={content.contentPosterImg} alt="" />
        <div className="p-3">
          <p>
            {content.userName} 평론가님의 <span className="text-red-400">한줄평</span>
          </p>
        </div>
      </div>
    </div>
  );
}

이런식으로 컴포넌트를 만들어주어 사용하고 있다 예시 코드는 리뷰카드인데 거의 동일하다

글쓰기는 ?

  • 일단 로그인을 해야만 글을 쓸수 있다
  • 로그인 -> 작품 검색 -> 리뷰 작성의 과정을 거치게 된다
  • 평점을 별을 클릭하여 정하고 한줄평과 그 외 덧붙일말을 쓸수가 있다

  • 리뷰를 쓰면 이렇게 확인할 수 있다 방금 쓴 따스한 리부
  review: {
    type: String,
    required: true,
  },
  addReview: {
    type: String,
  },
  • 이런식으로 추가 리뷰는 없어도 DB에 저장이 된다

한바퀴 돌아봅시다~

글쓰기

로그아웃 빼먹어서 따로 찍음

TMDB를 활용한 검색


마지막 검색기록을 보여준다

로컬스토리지를 이용한 다크모드

추가 예정 기능

  • 댓글 , 좋아요
  • 리뷰 삭제 , 업데이트

추가할 사항

  • 이미지 최적화에 대해 생각해보자
  • 다양한 예외사항을 생각하고 유저에게 상황에 맞는 UI를 제공해보자
  • 메인에서 필터링을 통해 리뷰 혹은 컨텐츠를 다양하게 보여주자

후기

앞으로는 이 홈페이지를 완성시키면서 겪는 문제 배우는 사항들을 기록할 것이다
꾸준히 끝까지 만들어서 배포까지 화이팅!

profile
안녕하시오?

0개의 댓글