Movie.tsx 6.67 KB
Newer Older
Daniel Puchala's avatar
Daniel Puchala committed
1
2
import Header from './Header';
import MovieCard from './MovieCard';
Daniel Puchala's avatar
Daniel Puchala committed
3
import { MovieCardMode } from '../models/types';
4
import { useState } from 'react';
Daniel Puchala's avatar
Daniel Puchala committed
5
import { useForm } from 'react-hook-form';
Daniel Puchala's avatar
Daniel Puchala committed
6
7
import { useParams } from 'react-router-dom';
import instance from '../models/axios';
8
import useSWR from 'swr';
Daniel Puchala's avatar
Daniel Puchala committed
9
import { getToken, getUser } from '../services/auth';
10
import formatDuration from '../services/formatDuration';
Daniel Puchala's avatar
Daniel Puchala committed
11
12
13
import Review from './Review';

function getAverageRating(review: any) {
Daniel Puchala's avatar
Daniel Puchala committed
14
  return (review.actingRating + review.ideaRating + review.scriptRating + review.musicRating + review.visualsEditRating) / 5;
Daniel Puchala's avatar
Daniel Puchala committed
15
}
Daniel Puchala's avatar
Daniel Puchala committed
16

Daniel Puchala's avatar
Daniel Puchala committed
17
export const Movie = () => {
18
  const [ showReviews, setShowReviews ] = useState<boolean>(false);
Daniel Puchala's avatar
Daniel Puchala committed
19
20
21
  const { register, handleSubmit, getValues, watch } = useForm();
  watch();

Daniel Puchala's avatar
Daniel Puchala committed
22
23
  const sendReview = async (data: any) => {
    const headers = {
Daniel Puchala's avatar
Daniel Puchala committed
24
25
      'Content-Type': 'application/json',
      'Authorization': getToken()
Daniel Puchala's avatar
Daniel Puchala committed
26
27
28
    };
    const reviewData = {
      ...data,
Daniel Puchala's avatar
Daniel Puchala committed
29
      movieId: id,
Daniel Puchala's avatar
Daniel Puchala committed
30
      userId: getUser()!.sub
Daniel Puchala's avatar
Daniel Puchala committed
31
    };
Daniel Puchala's avatar
Daniel Puchala committed
32
    await instance.post('reviews', reviewData, { headers });
Daniel Puchala's avatar
Daniel Puchala committed
33
    await mutateReviews();
Daniel Puchala's avatar
Daniel Puchala committed
34
35
36
    alert('Review created');
  };

Daniel Puchala's avatar
Daniel Puchala committed
37
  const { id } = useParams();
Daniel Puchala's avatar
Daniel Puchala committed
38
39
40
  const { data: movie, error: movieError } = useSWR(`movies/${id}`);
  const { data: reviews, error: reviewError, mutate: mutateReviews } = useSWR(`reviews/search/${id}`);
  const { data: recommended, error: recommendedError } = useSWR(`movies/${id}/recommended`);
41

Daniel Puchala's avatar
Daniel Puchala committed
42
43
  if (movieError || reviewError || recommendedError) return <div>failed to load</div>;
  if (!movie || !reviews || !recommended) return <div>loading...</div>;
44

Daniel Puchala's avatar
Daniel Puchala committed
45
  const recommendedMovies = recommended.slice(0, 5);
Daniel Puchala's avatar
Daniel Puchala committed
46
47

  return (
Daniel Puchala's avatar
Daniel Puchala committed
48
    <div>
Daniel Puchala's avatar
Daniel Puchala committed
49
      <Header/>
Daniel Puchala's avatar
Daniel Puchala committed
50
      <div className="grid grid-cols-3 h-[90vh]">
Daniel Puchala's avatar
Daniel Puchala committed
51
        <div className="flex flex-col col-span-2 h-full">
Daniel Puchala's avatar
Daniel Puchala committed
52
53
          <div className="flex flex-row p-4 border-solid border-r-4 border-slate-900 bg-slate-300 h-full w-full">
            <div className="p-4 flex-shrink-0 h-full w-2/5">
54
              <img className="h-full w-full" src={movie.poster} alt="Poster"/>
Daniel Puchala's avatar
Daniel Puchala committed
55
            </div>
Daniel Puchala's avatar
Daniel Puchala committed
56
            <div className="flex flex-col p-4 w-full">
57
              <p className="text-2xl font-bold">{movie.name}</p>
Daniel Puchala's avatar
Daniel Puchala committed
58
59
60
              {movie.genres &&
                  <p><b>Genres: </b>
                    {movie.genres.slice(0, -1).map((genre: any) => `${genre}, `)}
Daniel Puchala's avatar
Daniel Puchala committed
61
                    {`${movie.genres.at(-1)}`}
Daniel Puchala's avatar
Daniel Puchala committed
62
63
                  </p>
              }
Daniel Puchala's avatar
Daniel Puchala committed
64
              <p><b>Duration: </b>{formatDuration(movie.duration)}</p>
65
              <p>{movie.description}</p>
Daniel Puchala's avatar
Daniel Puchala committed
66
              <p className="text-xl mt-auto"><b>Director: </b>{movie.director.name}</p>
Daniel Puchala's avatar
Daniel Puchala committed
67
68
69
              {movie.actors &&
                  <p className="text-xl"><b>Actors: </b>
                    {movie.actors.slice(0, -1).map((actor: any) => `${actor.name}, `)}
Daniel Puchala's avatar
Daniel Puchala committed
70
                    {`${movie.actors.at(-1).name}`}
Daniel Puchala's avatar
Daniel Puchala committed
71
72
                  </p>
              }
Daniel Puchala's avatar
Daniel Puchala committed
73
              <button className="w-max p-4 self-center bg-blue-600 border-2 rounded-3xl border-slate-900"
Daniel Puchala's avatar
Daniel Puchala committed
74
                      onClick={() => setShowReviews((prevState => !prevState))}>
Daniel Puchala's avatar
Daniel Puchala committed
75
                {showReviews ? 'Show recommended movies' : 'Show reviews'}
76
              </button>
Daniel Puchala's avatar
Daniel Puchala committed
77
78
            </div>
          </div>
Daniel Puchala's avatar
Daniel Puchala committed
79
80

        </div>
Daniel Puchala's avatar
Daniel Puchala committed
81
        <div className={`h-full ${showReviews && 'hidden'}`}>
Daniel Puchala's avatar
Daniel Puchala committed
82
          <p className="text-2xl text-center font-bold">Recommended movies</p>
83
          <div className="flex flex-row flex-wrap p-4">
Daniel Puchala's avatar
Daniel Puchala committed
84
85
            {recommendedMovies.map((movie: any) => <MovieCard key={movie.id} {...movie}
                                                              mode={MovieCardMode.Recommend}/>)}
Daniel Puchala's avatar
Daniel Puchala committed
86
87
          </div>
        </div>
88
        <div className={`h-full flex flex-col overflow-hidden ${showReviews || 'hidden'}`}>
89
          <p className="text-2xl text-center font-bold">Reviews</p>
90
          <div className="overflow-y-scroll">
Daniel Puchala's avatar
Daniel Puchala committed
91
            {reviews.map((review: any) =>
92
93
              <Review averageRating={
                getAverageRating(review)}
94
                      id={review.id}
95
                      userId={+review.user.id}
96
97
                      text={review.text}
                      userName={review.user.name}
98
                      mutate={mutateReviews}
99
100
                      key={review.id}
              />
Daniel Puchala's avatar
Daniel Puchala committed
101
            )}
102
          </div>
103
          {getUser() &&
Daniel Puchala's avatar
Daniel Puchala committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
              <form
                  onSubmit={handleSubmit(sendReview)}
                  className="flex flex-col p-2 m-2 mt-auto bg-slate-300 border-4 rounded-3xl border-slate-900"
              >
                  <span className="text-2xl text-center font-bold">Write your review</span>
                  <label className="flex justify-between">
                      <span className="font-bold">Script: {getValues('scriptRating')}</span>
                      <input type="range" min={1} max={10} {...register('scriptRating', { required: true })}/>
                  </label>
                  <label className="flex justify-between">
                      <span className="font-bold">Idea: {getValues('ideaRating')}</span>
                      <input type="range" min={1} max={10} {...register('ideaRating', { required: true })}/>
                  </label>
                  <label className="flex justify-between">
                      <span className="font-bold">Visual edits: {getValues('visualsEditRating')}</span>
                      <input type="range" min={1} max={10} {...register('visualsEditRating', { required: true })}/>
                  </label>
                  <label className="flex justify-between">
                      <span className="font-bold">Music: {getValues('musicRating')}</span>
                      <input type="range" min={1} max={10} {...register('musicRating', { required: true })}/>
                  </label>
                  <label className="flex justify-between">
                      <span className="font-bold">Acting: {getValues('actingRating')}</span>
                      <input type="range" min={1} max={10} {...register('actingRating', { required: true })}/>
                  </label>
                  <label>
Daniel Puchala's avatar
Daniel Puchala committed
130
              <textarea
Daniel Puchala's avatar
Daniel Puchala committed
131
132
133
                  className="w-full border-2 border-slate-900"
                  {...register('text', { required: true, minLength: 1 })}
                  placeholder={'Write your review here.'}
Daniel Puchala's avatar
Daniel Puchala committed
134
              />
Daniel Puchala's avatar
Daniel Puchala committed
135
136
137
138
139
140
                  </label>
                  <button type="submit"
                          className="w-max p-2 self-center bg-blue-600 border-2 rounded-3xl border-slate-900">
                      Send review
                  </button>
              </form>
141
          }
142
        </div>
Daniel Puchala's avatar
Daniel Puchala committed
143

Daniel Puchala's avatar
Daniel Puchala committed
144
145
146
147
148
149
      </div>
    </div>
  );
};

export default Movie;