From f0154a514c0ad0ecf96d8a551073e909e85698b1 Mon Sep 17 00:00:00 2001 From: Lucas Delanier Date: Tue, 28 Feb 2023 23:02:26 +0100 Subject: [PATCH] Code clean :tada: --- components/HeaderMovieComponent.tsx | 41 +++ components/MovieListComponent.tsx | 103 ++++++ components/StarsComponent.tsx | 46 +++ components/TimerComponent.tsx | 44 +++ model/review.tsx | 12 +- navigation/index.tsx | 2 +- redux/actions/actionGetTrendingID.tsx | 29 +- redux/reducers/appReducer.tsx | 18 +- screens/FavoriteScreen.tsx | 142 ++++---- screens/HomeScreen.tsx | 256 ++++--------- screens/InfoScreen.tsx | 500 ++++++++++++++++++-------- screens/WatchLaterScreen.tsx | 186 ++++------ 12 files changed, 800 insertions(+), 579 deletions(-) create mode 100644 components/HeaderMovieComponent.tsx create mode 100644 components/MovieListComponent.tsx create mode 100644 components/StarsComponent.tsx create mode 100644 components/TimerComponent.tsx diff --git a/components/HeaderMovieComponent.tsx b/components/HeaderMovieComponent.tsx new file mode 100644 index 0000000..f7cca48 --- /dev/null +++ b/components/HeaderMovieComponent.tsx @@ -0,0 +1,41 @@ +import {StyleSheet, Text, View} from "react-native"; +import * as React from "react"; +import Stars from "./StarsComponent"; +import Movie from "../model/Movie"; + +type headerMovieProps = { + movie: Movie + +} + +export function HeaderMovie(props: headerMovieProps) { + + function formatTime(time: number) { + const hours = Math.floor(time / 60); + const minutes = time % 60; + return `${hours}h ${minutes < 10 ? `0${minutes}` : minutes}m`; + } + + const styles = StyleSheet.create({ + circle: { + width: 6, + height: 6, + borderRadius: 100 / 2, + marginTop: 4, + backgroundColor: "lightgray", + marginHorizontal: 8 + }, + }); + + return ( + {props.movie.original_title} + + {`${props.movie.release_date}`} + + {`${props.movie.genres[0]} ${props.movie.genres[1] !== undefined ? ", " + props.movie.genres[1] : ""}`} + + {`${formatTime(props.movie.runtime)}`} + + + ); +} diff --git a/components/MovieListComponent.tsx b/components/MovieListComponent.tsx new file mode 100644 index 0000000..3efb492 --- /dev/null +++ b/components/MovieListComponent.tsx @@ -0,0 +1,103 @@ +import Movie from "../model/Movie.js"; +import {Image, StyleSheet, Text, View} from "react-native"; +import {LinearGradient} from "expo-linear-gradient"; +import Stars from "./StarsComponent"; +import * as React from "react"; + +type MovieListProps = { + movie: Movie + +} + +export function MovieListComponent(props: MovieListProps) { + function formatTime(time: number) { + const hours = Math.floor(time / 60); + const minutes = time % 60; + return `${hours}h ${minutes < 10 ? `0${minutes}` : minutes}m`; + } + + const styles = StyleSheet.create({ + filmCard: { + width: 70, + height: 110, + borderRadius: 8, + }, + body: { + height: 130, + + borderRadius: 20, + justifyContent: "flex-start", + flexDirection: 'row', + marginHorizontal: 10, + marginVertical: 7, + paddingHorizontal: 10, + backgroundColor: "#1D1D1D", + alignItems: "center", + borderWidth: 1.5, + borderColor: "#1F1F1F" + }, + section: { + height: 130, + width: "85%", + justifyContent: "center", + flexDirection: 'column', + paddingRight: 20, + paddingLeft: 20, + }, + h1: { + color: "white", + fontWeight: "700", + fontSize: 21, + }, + infoSection: { + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + width: "100%" + }, + top: { + flexDirection: "row", + alignItems: "center" + }, + h3: { + color: "grey", + fontWeight: "600" + }, + vote: { + paddingLeft: 7, + color: "white", + fontWeight: "bold", + fontSize: 13 + } + }); + + return ( + + + + + + + {props.movie.original_title} + + + + {props.movie.vote_average.toFixed(1)} + + + {formatTime(props.movie.runtime)} + + {props.movie.overview} + + + + ); +} \ No newline at end of file diff --git a/components/StarsComponent.tsx b/components/StarsComponent.tsx new file mode 100644 index 0000000..417f618 --- /dev/null +++ b/components/StarsComponent.tsx @@ -0,0 +1,46 @@ +import {Image, View} from "react-native"; +import * as React from "react"; + + +type StarsProps = { + note: number + size: number + +} + +export function Stars(props: StarsProps) { + let imageSource; + let note = props.note / 2; + if (note < 0.5) + imageSource = require('../assets/images/0.5stars_vote.png'); + else if (note < 1) + imageSource = require('../assets/images/1stars_vote.png'); + else if (note < 1.5) + imageSource = require('../assets/images/1.5stars_vote.png'); + else if (note < 2) + imageSource = require('../assets/images/2stars_vote.png'); + else if (note < 2.5) + imageSource = require('../assets/images/2.5stars_vote.png'); + else if (note < 3) + imageSource = require('../assets/images/3stars_vote.png'); + else if (note < 3.5) + imageSource = require('../assets/images/3.5stars_vote.png'); + else if (note < 4) + imageSource = require('../assets/images/4stars_vote.png'); + else if (note < 4.5) + imageSource = require('../assets/images/4.5stars_vote.png'); + else if (note < 5) + imageSource = require('../assets/images/5stars_vote.png'); + + return ( + + + + ); +}; + +export default Stars; \ No newline at end of file diff --git a/components/TimerComponent.tsx b/components/TimerComponent.tsx new file mode 100644 index 0000000..8f55e65 --- /dev/null +++ b/components/TimerComponent.tsx @@ -0,0 +1,44 @@ +import {Image, Text, View} from "react-native"; +import * as React from "react"; + +type TimerProps = { + hours: number + minutes: number + seconds: number + +} + +export function Timer(props: TimerProps) { + return ( + + Nouvelle collection dans + + {`${props.hours.toString().padStart(2, '0')}:`} + {`${props.minutes.toString().padStart(2, '0')}:`} + {`${props.seconds.toString().padStart(2, '0')}`} + + + ); +} + +export function Timer2(props: TimerProps) { + return ( + + Nouvelle collection dans + + + {`${props.hours.toString().padStart(2, '0')}:`} + {`${props.minutes.toString().padStart(2, '0')}:`} + {`${props.seconds.toString().padStart(2, '0')}`} + + + ); +} \ No newline at end of file diff --git a/model/review.tsx b/model/review.tsx index a08f5a2..1aaaf79 100644 --- a/model/review.tsx +++ b/model/review.tsx @@ -3,19 +3,19 @@ class Review { public pseudo: string - public profil_path: string + public profile_path: string public date: string - constructor(message: string, profil_path: string, date: string, pseudo: string) { + constructor(message: string, profile_path: string, date: string, pseudo: string) { this.message = message; - if (profil_path === null) { - this.profil_path = "https://thumbs.dreamstime.com/b/profil-vectoriel-avatar-par-d%C3%A9faut-utilisateur-179376714.jpg"; + if (profile_path == null) { + this.profile_path = "https://thumbs.dreamstime.com/b/profil-vectoriel-avatar-par-d%C3%A9faut-utilisateur-179376714.jpg"; } else { - this.profil_path = 'https://image.tmdb.org/t/p/w185' + profil_path; + this.profile_path = 'https://image.tmdb.org/t/p/w185' + profile_path; } - + console.log("profil_path", this.profile_path) this.date = date.substring(0, 10); this.pseudo = pseudo; diff --git a/navigation/index.tsx b/navigation/index.tsx index afe6b18..59f82d8 100644 --- a/navigation/index.tsx +++ b/navigation/index.tsx @@ -40,7 +40,7 @@ export default function Navigation({colorScheme}: { colorScheme: ColorSchemeName //console.log("test1:", trendingMovies); loadTrendingID(); } catch (e) { - console.warn(e); + //console.warn(e); } finally { // Tell the application to render setAppIsReady(true); diff --git a/redux/actions/actionGetTrendingID.tsx b/redux/actions/actionGetTrendingID.tsx index 45a862c..aba1695 100644 --- a/redux/actions/actionGetTrendingID.tsx +++ b/redux/actions/actionGetTrendingID.tsx @@ -1,16 +1,8 @@ -import { - FETCH_TRENDING_MOVIE, - FETCH_TRENDING_ID, - POP_FIRST_TRENDING, - ADD_WATCHLATER, - FETCH_WATCHLATER, - ADD_FAVOURITE, - FETCH_FAVOURITE -} from '../constants'; +import {ADD_FAVOURITE, ADD_WATCHLATER, FETCH_FAVOURITE, FETCH_TRENDING_MOVIE, FETCH_WATCHLATER, POP_FIRST_TRENDING} from '../constants'; import config from "../../constants/config"; import Movie from "../../model/Movie"; -export const getWatchLaterMovies = (WatchLaterList: Movie[]) => { +/*export const getWatchLaterMovies = (WatchLaterList: Movie[]) => { return { type: FETCH_WATCHLATER, payload: WatchLaterList, @@ -22,7 +14,7 @@ export const getFavouriteMovies = (FavouriteList: Movie[]) => { type: FETCH_FAVOURITE, payload: FavouriteList, }; -} +}*/ export const fetchWatchLater = (WatchLaterList: Movie[]) => { return { @@ -66,21 +58,17 @@ export const getTrendingID = () => { const MovieList: Movie[] = []; Promise.all(idList.map(async elt => { try { - const infoPromise = await fetch(config.base_url + "movie/" + elt + "?api_key=" + config.api_key + "&language=fr-FR"); - //const infoJson = await infoPromise.json(); - //console.log('infos---------', infoJson); - //MovieList.push(new Movie(infoJson["original_title"], infoJson["poster_path"],infoJson["runtime"], infoJson["vote_average"], infoJson["release_date"])) - return infoPromise; + return await fetch(config.base_url + "movie/" + elt + "?api_key=" + config.api_key + "&language=fr-FR"); } catch (err) { - //console.log('ErrorGet---------', err); + console.log('Error', err); } })).then(function (responses) { + // @ts-ignore Promise.all(responses.map(result => result.json())) .then(function (elements) { elements.map(elt => { const infoJson = elt; const genreRow: String[] = []; - const videoPath: String = ""; // @ts-ignore elt["genres"].map(genre => { genreRow.push(genre.name); @@ -90,17 +78,16 @@ export const getTrendingID = () => { MovieList.push(new Movie(infoJson["id"], infoJson["title"], infoJson["poster_path"], infoJson["runtime"], infoJson["vote_average"], infoJson["release_date"], genreRow, infoJson["overview"], infoJson["backdrop_path"])) }) try { - //console.log("tortue", MovieList) dispatch(setinfoMovie(MovieList)); } catch (err) { - //console.log('ErrorGet---------', err); + console.log('Error', err); } }) }); } catch (error) { - console.log('Error---------', error); + console.log('Error', error); } } } diff --git a/redux/reducers/appReducer.tsx b/redux/reducers/appReducer.tsx index a044e06..6d10faa 100644 --- a/redux/reducers/appReducer.tsx +++ b/redux/reducers/appReducer.tsx @@ -1,12 +1,4 @@ -import { - POP_FIRST_TRENDING, - FETCH_TRENDING_MOVIE, - FETCH_TRENDING_ID, - ADD_WATCHLATER, - FETCH_WATCHLATER, - ADD_FAVOURITE, - FETCH_FAVOURITE -} from "../constants"; +import {POP_FIRST_TRENDING, FETCH_TRENDING_MOVIE, FETCH_TRENDING_ID, ADD_WATCHLATER, FETCH_WATCHLATER, ADD_FAVOURITE, FETCH_FAVOURITE} from "../constants"; import Movie from "../../model/Movie"; const initialState = { @@ -15,10 +7,8 @@ const initialState = { watchLaterMovies: [] as Movie[], favouriteMovies: [] as Movie[], } - // @ts-ignore export default appReducer = (state = initialState, action) => { - console.log(action.payload) switch (action.type) { case FETCH_TRENDING_ID: // @ts-ignore @@ -32,13 +22,13 @@ export default appReducer = (state = initialState, action) => { case FETCH_TRENDING_MOVIE: return {...state, trendingMovies: action.payload}; case POP_FIRST_TRENDING: - return {...state, trendingMovies: [...state.trendingMovies.filter((item : Movie) => item !== action.payload)]}; + return {...state, trendingMovies: [...state.trendingMovies.filter((item: Movie) => item !== action.payload)]}; case ADD_WATCHLATER: // @ts-ignore - return {...state,watchLaterMovies: [action.payload,...state.watchLaterMovies]}; + return {...state, watchLaterMovies: [action.payload, ...state.watchLaterMovies]}; case ADD_FAVOURITE: // @ts-ignore - return {...state, favouriteMovies: [action.payload,...state.favouriteMovies]}; + return {...state, favouriteMovies: [action.payload, ...state.favouriteMovies]}; default: return state; } diff --git a/screens/FavoriteScreen.tsx b/screens/FavoriteScreen.tsx index b8450c3..05b287c 100644 --- a/screens/FavoriteScreen.tsx +++ b/screens/FavoriteScreen.tsx @@ -1,28 +1,32 @@ import {FlatList, StyleSheet, SafeAreaView, Text, View, Image, TextInput, TouchableHighlight} from 'react-native'; import * as React from "react"; -import {BadgeFilm, Stars} from "./HomeScreen"; import {FontAwesomeIcon} from "@fortawesome/react-native-fontawesome"; -import {faHeart} from "@fortawesome/free-solid-svg-icons"; -import LinearGradient from 'react-native-linear-gradient'; +import {faClock} from "@fortawesome/free-solid-svg-icons"; import {RootTabScreenProps} from "../types"; import {useSafeAreaInsets} from "react-native-safe-area-context"; import {useDispatch, useSelector} from 'react-redux'; import {useEffect, useState} from 'react'; -import {getTrendingID, getFavourite, getFavouriteMovies} from "../redux/actions/actionGetTrendingID"; +import {getFavourite} from "../redux/actions/actionGetTrendingID"; import Movie from "../model/Movie"; -import Swipeable from "react-native-gesture-handler/Swipeable"; +import {MovieListComponent} from "../components/MovieListComponent"; + + +export default function FavoriteScreen({navigation}: RootTabScreenProps<'Favorite'>) { -export default function FavoriteScreen({ navigation }: RootTabScreenProps<'Favorite'>) { const [search, setSearch] = useState(''); + const [filteredDataSource, setFilteredDataSource] = useState([]); - const [masterDataSource, setMasterDataSource] = useState([]); + + const [masterDataSource] = useState([]); + const insets = useSafeAreaInsets(); + const styles = StyleSheet.create({ container: { flex: 1, - paddingTop: 22, - backgroundColor: "#232323" + paddingTop: insets.top + 22, + backgroundColor: "#0E0E0E" }, linearGradient: { flex: 1, @@ -41,17 +45,52 @@ export default function FavoriteScreen({ navigation }: RootTabScreenProps<'Favor height: 100, borderRadius: 8, }, + searchSection: { + height: 40, + width: 400, + backgroundColor: "grey", + borderRadius: 20, + marginVertical: 10, + alignSelf: "center" + }, + searchBar: { + width: '100%', + height: 40, + marginHorizontal: 20 + }, + titlePage: { + height: 50, + justifyContent: "flex-start", + flexDirection: 'row', + paddingHorizontal: 20, + marginBottom: 15, + marginVertical: 5, + alignItems: "flex-end" + }, + icon: { + marginBottom: -5, + marginRight: 20 + }, + delimiter: { + height: 2, + width: 400, + resizeMode: "stretch" + }, + h1: { + color: "white", + fontSize: 30 + } }); - - const dispatch = useDispatch(); // @ts-ignore const favouriteMovies = useSelector(state => state.appReducer.favouriteMovies); + + const dispatch = useDispatch(); + useEffect(() => { const loadFavourite = async () => { // @ts-ignore await dispatch(getFavourite()); }; - console.log("test11111:", favouriteMovies); loadFavourite(); }, [dispatch]); @@ -74,87 +113,26 @@ export default function FavoriteScreen({ navigation }: RootTabScreenProps<'Favor return ( - - - Favorite + + + Watch Later - - searchFilterFunction(text)} + + + searchFilterFunction(text)} value={search} > item.original_title} - renderItem={({item}) => } + // @ts-ignore + renderItem={({item}) => navigation.navigate("Info", {"item": item})}>} /> ); } -type ListWidgetProps = { - movie: Movie -} - -export function ListWidget(props: ListWidgetProps) { - const insets = useSafeAreaInsets(); - - const styles = StyleSheet.create({ - filmCard: { - width: 90, - height: 130, - borderRadius: 8, - }, - }); - - function formatTime(time: number) { - console.log(time); - const hours = Math.floor(time / 60); - const minutes = time % 60; - return `${hours}h ${minutes < 10 ? `0${minutes}` : minutes}m`; - } - - return ( - - - - {props.movie.original_title} - - - - {props.movie.vote_average.toFixed(1)} - - {formatTime(props.movie.runtime)} - - {props.movie.overview} - - - ); -} \ No newline at end of file diff --git a/screens/HomeScreen.tsx b/screens/HomeScreen.tsx index 3a01253..9c572db 100644 --- a/screens/HomeScreen.tsx +++ b/screens/HomeScreen.tsx @@ -1,39 +1,28 @@ import * as React from 'react'; -import { - Button, - TouchableOpacity, - ScrollView, - View, - Text, - StyleSheet, - Image, - ImageBackground, - SafeAreaView, - ActivityIndicator, FlatList -} from 'react-native'; +import {TouchableOpacity, View, Text, StyleSheet, Image, ImageBackground, SafeAreaView} from 'react-native'; import {RootStackScreenProps} from "../types"; import {useEffect, useRef, useState} from "react"; import {useSafeAreaInsets} from "react-native-safe-area-context"; -import {addMovieToWatchLater, addMovieToFavourite, getTrendingID, removeMovieTrending,} from "../redux/actions/actionGetTrendingID"; +import {addMovieToWatchLater, addMovieToFavourite, removeMovieTrending,} from "../redux/actions/actionGetTrendingID"; import {useDispatch, useSelector} from 'react-redux'; import Movie from "../model/Movie"; -import * as url from "url"; import moment from 'moment'; import CardsSwipe from 'react-native-cards-swipe'; import AnimatedLottieView from "lottie-react-native"; +import {Timer, Timer2} from "../components/TimerComponent"; +import {HeaderMovie} from "../components/HeaderMovieComponent"; export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { // @ts-ignore const trendingMovies = useSelector(state => state.appReducer.trendingMovies); - + const dispatch = useDispatch(); const [hours, setHours] = useState(0); const [minutes, setMinutes] = useState(0); const [seconds, setSeconds] = useState(0); const [displayIndex, setdisplayIndex] = useState(0); - var swiper = null; - //console.log("liste [0]: ", trendingMovies[0]); + var swiper: any = null; const insets = useSafeAreaInsets(); @@ -49,7 +38,6 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { width: '100%', paddingTop: insets.top, }, - container: { flex: 1, }, @@ -82,21 +70,63 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', }, - circle: { - width: 6, - height: 6, - borderRadius: 100 / 2, - marginTop: 4, - backgroundColor: "lightgray", - marginHorizontal: 8 + explanation: { + color: "grey", + fontWeight: "400", + paddingHorizontal: 70, + textAlign: "center" + }, + h1: { + color: "white", + fontWeight: "600", + fontSize: 35 + }, + congratsSection: { + alignItems: "center", + width: "100%", + height: "100%", + justifyContent: "center", + zIndex: 1 + }, + button: { + resizeMode: "stretch", + height: '55%', + aspectRatio: 1, + }, + buttonSection: { + flexDirection: 'row', + alignItems: 'flex-end', + justifyContent: "space-evenly", + paddingHorizontal: 30, + width: '100%', + position: "absolute", + top: "74%", + zIndex: 30 + }, + posterBackground: { + width: "150%", + height: "150%", + justifyContent: "center", + alignItems: "center", + opacity: 0.55, + position: 'absolute', + left: "-50%", + top: "-50%" }, + finishBackground: { + width: "110%", + height: "110%", + justifyContent: "center", + alignItems: "center", + opacity: 0.15, + position: "absolute", + zIndex: 0 + } }); - const dispatch = useDispatch(); - useEffect(() => { const interval = setInterval(() => { const today = moment(); @@ -120,16 +150,10 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { const s = Math.floor((difference % (1000 * 60)) / 1000); setSeconds(s); - //console.log("timer", h, m, s); }); setTimeout(() => interval, 10000); }, []); - type ItemProps = { - movie: Movie - - } - function addWatchLater(props: Movie) { dispatch(addMovieToWatchLater(props)); dispatch(removeMovieTrending(props)); @@ -157,27 +181,12 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { } } - function formatTime(time: number) { - const hours = Math.floor(time / 60); - const minutes = time % 60; - return `${hours}h ${minutes < 10 ? `0${minutes}` : minutes}m`; - } - return ( <> @@ -188,32 +197,12 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { - - {trendingMovies[displayIndex].original_title} - - {`${trendingMovies[displayIndex].release_date}`} - - {`${trendingMovies[displayIndex].genres[0]} ${trendingMovies[displayIndex].genres[1] !== undefined ? ", " + trendingMovies[0].genres[1] : ""}`} - - {`${formatTime(trendingMovies[displayIndex].runtime)}`} - - - + { @@ -223,7 +212,6 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { cards={trendingMovies} loop={true} onSwipedLeft={(index) => { - console.log(index) if (index < trendingMovies.length - 1) { setdisplayIndex(index + 1); @@ -251,7 +239,7 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { /> - + { addWatchLater(trendingMovies[displayIndex]); @@ -259,7 +247,7 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { }}> ) { popFirstTrending(trendingMovies[displayIndex]); }}> @@ -278,45 +264,24 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { } }> - - Nouvelle collection dans - - {`${hours.toString().padStart(2, '0')}:`} - {`${minutes.toString().padStart(2, '0')}:`} - {`${seconds.toString().padStart(2, '0')}`} - + )} {trendingMovies.length === 0 && ( - - Félicitations ! + + Félicitations ! - Vous avez fini la collection du jour. + Vous avez fini la collection du jour. {"\n"}Revenez à la fin du décompte pour découvrir de nouvelles propositions. - - Nouvelle collection dans - - - {`${hours.toString().padStart(2, '0')}:`} - {`${minutes.toString().padStart(2, '0')}:`} - {`${seconds.toString().padStart(2, '0')}`} - + @@ -328,95 +293,12 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) { ) } -type BadgeGenreProps = { - name: String - isSelected: Boolean -} -export function BadgeGenre(props: BadgeGenreProps) { - if (props.isSelected === false) { - return ( - - {props.name} - - - ); - } else { - return ( - - {props.name} - - - ); - } -} -type BadgeFilmProps = { - name: String -} -export function BadgeFilm(props: BadgeFilmProps) { - return ( - - {props.name} - - - ); - - -} - -type StarsProps = { - note: number - size: number - -} - -export function Stars(props: StarsProps) { - let imageSource; - let note = props.note / 2; - if (note < 0.5) - imageSource = require('../assets/images/0.5stars_vote.png'); - else if (note < 1) - imageSource = require('../assets/images/1stars_vote.png'); - else if (note < 1.5) - imageSource = require('../assets/images/1.5stars_vote.png'); - else if (note < 2) - imageSource = require('../assets/images/2stars_vote.png'); - else if (note < 2.5) - imageSource = require('../assets/images/2.5stars_vote.png'); - else if (note < 3) - imageSource = require('../assets/images/3stars_vote.png'); - else if (note < 3.5) - imageSource = require('../assets/images/3.5stars_vote.png'); - else if (note < 4) - imageSource = require('../assets/images/4stars_vote.png'); - else if (note < 4.5) - imageSource = require('../assets/images/4.5stars_vote.png'); - else if (note < 5) - imageSource = require('../assets/images/5stars_vote.png'); - - return ( - - - - ); -}; diff --git a/screens/InfoScreen.tsx b/screens/InfoScreen.tsx index ec21338..adc4c2f 100644 --- a/screens/InfoScreen.tsx +++ b/screens/InfoScreen.tsx @@ -1,81 +1,362 @@ import * as React from 'react'; -import { - Button, - TouchableOpacity, - ScrollView, - View, - Text, - StyleSheet, - Image, - ImageBackground, - SafeAreaView, - ActivityIndicator, FlatList, TouchableHighlight -} from 'react-native'; +import {TouchableOpacity, ScrollView, View, Text, StyleSheet, Image, SafeAreaView, FlatList} from 'react-native'; import {RootStackScreenProps} from "../types"; import {useSafeAreaInsets} from "react-native-safe-area-context"; - import Movie from "../model/Movie"; - import {LinearGradient} from 'expo-linear-gradient'; -import {Stars} from "./HomeScreen"; import {useEffect, useState} from "react"; import config from "../constants/config"; import YoutubeIframe from "react-native-youtube-iframe"; -import Icon from "react-native-ionicons"; import Ionicons from "@expo/vector-icons/Ionicons"; import MinimalMovie from "../model/MinimalMovie"; -import {ListWidget} from "./WatchLaterScreen"; import Review from "../model/review"; +import Stars from "../components/StarsComponent"; +import minimalMovie from "../model/MinimalMovie"; export default function InfoScreen({navigation, route}: RootStackScreenProps<'Info'>) { // @ts-ignore const item: Movie = route.params.item + const insets = useSafeAreaInsets(); + + const [trailerPath, setTrailerPath] = useState(""); + + const [similarMovies, setSimilarMovies] = useState([]); + + const [review, setReview] = useState([]); + + const [credit, setCredit] = useState(); + + const [paddingTopBackground, setPaddingTopBackground] = useState(0); + + const [opacityBackground, setOpacityBackground] = useState(0.7); + + const [scaleBackground, setScaleBackground] = useState(1); + + function formatTime(time: number) { + const hours = Math.floor(time / 60); + const minutes = time % 60; + return `${hours}h ${minutes < 10 ? `0${minutes}` : minutes}m`; + } + + const handleScroll = (event: any) => { + const {y} = event.nativeEvent.contentOffset; + let padTop = y / -5; + if (padTop <= 0) + + setPaddingTopBackground(y / -5); + setOpacityBackground(0.5 - y / 500); + let scale = 1 - y / -1000 + if (scale >= 1) + setScaleBackground(scale); + }; + + type creditItem = [string, string, number]; + + type creditProps = { + data: creditItem[]; + }; + + function CreditList({data}: creditProps) { + const renderItem = ({item}: { item: creditItem }) => ( + + + + + {item[2].toFixed(1).toString()} + + + + + {item[0]} + + ); + + return ( + item[0]} + /> + ); + } + + type SimilarMovieProps = { + movie: minimalMovie; + }; + + function SimilarMovie(props: SimilarMovieProps) { + return ( + + + {props.movie.original_title} + + ); + } + + type ReviewProps = { + review: Review; + }; + + function ReviewComponent(props: ReviewProps) { + return ( + + + + + + {props.review.pseudo} + {props.review.date} + + + + + {props.review.message} + + ); + } + + type InfoBadgeProps = { + texte: string + + } + + function InfoBadge(props: InfoBadgeProps) { + return ( + {props.texte} + ); + } + const styles = StyleSheet.create({ background1: { height: '100%', width: '100%', paddingTop: insets.top, }, + body: { + backgroundColor: "#0E0E0E" + }, + backgroundSection: { + height: "100%", + width: "100%", + position: "absolute" + }, + back_drop: { + height: "45%", + top: paddingTopBackground, + width: '100%', + opacity: opacityBackground, + position: "absolute", + + transform: [{scale: scaleBackground}], + }, + gradientFade: { + height: "30%", + top: "25%" + }, + backButton: { + position: "absolute", + top: 10, + left: 5 + }, + list: { + height: "100%" + }, + section1: { + paddingHorizontal: 35 + }, + title: { + color: "white", + fontSize: 43, + fontWeight: "bold", + paddingBottom: 10, + paddingTop: "45%" + }, + characteristics: { + flexDirection: "row", + width: "100%", + justifyContent: "flex-start" + }, + stars: { + flexDirection: "row", + width: "100%", + justifyContent: "flex-start", + alignItems: "center", + paddingBottom: 30 + }, + starsLabel: { + color: "#FFC42D", + fontWeight: "bold", + paddingLeft: 10, + fontSize: 16 + }, + player: { + borderRadius: 10, + overflow: "hidden" + }, + resume: { + color: "#B3B3B3", + paddingTop: 30, + fontSize: 17 + }, + creditSection: { + paddingTop: 30 + }, + creditTitle: { + color: "#2998FD", + paddingBottom: 20, + paddingLeft: 35, + fontSize: 17, + fontWeight: "600" + }, + similarSection: { + paddingTop: 30 + }, + similarTitle: { + color: "#2998FD", + paddingLeft: 35, + fontSize: 17, + fontWeight: "600", + paddingBottom: 20 + }, + similarContainer: { + width: 90, + marginHorizontal: 7 + }, + similarPoster: { + height: 130, + width: 90, + borderRadius: 8 + }, + similarTitleFilm: { + color: "#DADADA", + paddingTop: 5, + fontWeight: "300" + }, + reviewSection: { + paddingTop: 30 + }, + reviewTitle: { + color: "#2998FD", + paddingLeft: 35, + fontSize: 17, + fontWeight: "600", + paddingBottom: 10 + }, + reviewContainer: { + marginHorizontal: 7, + width: 300, + padding: 20, + backgroundColor: "#09090F", + marginVertical: 10, + borderRadius: 14, + borderWidth: 0.8, + borderColor: "rgba(223,223,223,0.14)" + }, + reviewInfo: { + flexDirection: "row", + paddingBottom: 20 + }, + imageProfile: { + height: 50, + width: 50, + borderRadius: 100 + }, + infoContainer: { + paddingLeft: 10, + flexDirection: "row", + justifyContent: "space-between", + width: "80%", + alignItems: "center" + }, + pseudo: { + color: "white", + paddingTop: 5, + fontWeight: "700", + fontSize: 16 + }, + date: { + color: "grey", + paddingTop: 5, + fontWeight: "500", + fontSize: 14 + }, + message: { + color: "#B3B3B3", + paddingTop: 5, + fontWeight: "400" + }, + creditContainer: { + width: 90, + marginHorizontal: 7, + alignItems: "center" + }, + bubble: { + justifyContent: "center" + }, + photo: { + height: 90, + width: 90, + borderRadius: 200, + borderWidth: 3, + borderColor: "rgba(255,255,255,0.8)" + }, + popularityDot: { + backgroundColor: "white", + borderRadius: 20, + padding: 2, + paddingHorizontal: 5, + justifyContent: "center", + alignItems: "center", + position: "absolute", + bottom: 0, + right: 0, + flexDirection: "row" + }, + popularityLabel: { + color: "black", + fontWeight: "500", + paddingRight: 4 + }, + creditName: { + color: "#DADADA", + paddingTop: 5, + fontWeight: "300" + } }); - const [trailerPath, setTrailerPath] = useState(""); - const [similarMovies, setsimilarMovies] = useState([]); - const [review, setReview] = useState([]); - const [credit, setCredit] = useState(); - const [paddingtopbackgroud, setpaddingtopbackgroud] = useState(0); - const [opacitybackground, setopacitybackground] = useState(0.7); - const [scalebackground, setscalebackground] = useState(1); + const getTriller = async () => { const trailerResponse = (await fetch(config.base_url + "movie/" + item.id + "/videos?api_key=" + config.api_key + "&language=fr-FR")); const trailerJson = await trailerResponse.json(); - console.log("trailer", trailerJson) + //console.log("trailer", trailerJson) // @ts-ignore const trailer_key = trailerJson.results.slice(0, 1).map((elt) => { if (elt["type"] === "Trailer" && elt["site"] === "YouTube") { return elt["key"]; } }); - console.log("key", trailer_key) + //console.log("key", trailer_key) setTrailerPath(trailer_key); } - const getCredits = async () => { const creditResponse = (await fetch(config.base_url + "movie/" + item.id + "/credits?api_key=" + config.api_key + "&language=fr-FR")); const creditJson = await creditResponse.json(); - console.log("credittttttt", creditJson) + //console.log("credittttttt", creditJson) // @ts-ignore let creditList = creditJson.cast.map((elt) => { if (elt["popularity"]) - return [elt["name"], 'https://image.tmdb.org/t/p/w500' + elt["profile_path"], elt["popularity"]] + return [elt["name"], 'https://image.tmdb.org/t/p/w185' + elt["profile_path"], elt["popularity"]] }); - creditList = creditList.slice(0, 5).sort((a: [fullname: string, profil_path: string, popularity: number], b: [fullname: string, profil_path: string, popularity: number]) => b[2] - a[2]); + creditList = creditList.slice(0, 5).sort((a: [fullname: string, profile_path: string, popularity: number], b: [fullname: string, profil_path: string, popularity: number]) => b[2] - a[2]); - console.log("credit", creditList); + //console.log("credit", creditList); setCredit(creditList); } - const getSimilarMovies = async () => { const SimilarMoviesResponse = (await fetch(config.base_url + "movie/" + item.id + "/recommendations?api_key=" + config.api_key + "&language=fr-FR")); @@ -84,15 +365,16 @@ export default function InfoScreen({navigation, route}: RootStackScreenProps<'In const SimilarMoviesList = SimilarMoviesJson.results.slice(0, 10).map((elt) => { return new MinimalMovie(elt["original_title"], elt["poster_path"]) }); - console.log("similar", SimilarMoviesList); - setsimilarMovies(SimilarMoviesList); + //console.log("similar", SimilarMoviesList); + setSimilarMovies(SimilarMoviesList); } const getReview = async () => { const ReviewResponse = (await fetch(config.base_url + "movie/" + item.id + "/reviews?api_key=" + config.api_key + "&language=us-EN&page=1")); const ReviewJson = await ReviewResponse.json(); // @ts-ignore - let ReviewList = ReviewJson.results.map((elt) => { + let ReviewList = ReviewJson.results.slice(0, 5).map((elt) => { + // @ts-ignore const newreview = new Review(elt["content"], elt["author_details"].avatar_path, elt["created_at"], elt["author"]) return newreview }); @@ -100,81 +382,25 @@ export default function InfoScreen({navigation, route}: RootStackScreenProps<'In return array.findIndex((item: Review) => item.pseudo === review.pseudo) === index; }); - console.log("review", ReviewJson.results); + //console.log("review", ReviewJson.results); setReview(ReviewList); } useEffect(() => { - getReview(); + getTriller(); getSimilarMovies(); getCredits(); + getReview(); }, []); - function formatTime(time: number) { - const hours = Math.floor(time / 60); - const minutes = time % 60; - return `${hours}h ${minutes < 10 ? `0${minutes}` : minutes}m`; - } - - type creditItem = [string, string, number]; - type creditProps = { - data: creditItem[]; - }; - const handleScroll = (event: any) => { - const {y} = event.nativeEvent.contentOffset; - let padTop = y / -5; - if (padTop <= 0) - - setpaddingtopbackgroud(y / -5); - setopacitybackground(0.5 - y / 500); - let scale = 1 - y / -1000 - if (scale >= 1) - setscalebackground(scale); - }; - - - function CreditList({data}: creditProps) { - const renderItem = ({item}: { item: creditItem }) => ( - - - - - {item[2].toFixed(1).toString()} - - - - - {item[0]} - - ); - - return ( - item[0]} - /> - ); - } return ( - - + + - @@ -193,90 +419,64 @@ export default function InfoScreen({navigation, route}: RootStackScreenProps<'In navigation.goBack()} style={{zIndex: 100}}> - + - - - {item.original_title} - + + {item.original_title} + - + - {item.vote_average.toFixed(1)} + {item.vote_average.toFixed(1)} - {trailerPath !== "" && ( - - )} - - - {item.overview} + {trailerPath !== "" && ()} + {item.overview} {credit !== undefined && ( - <> - Crédits - + + Crédits + + )} {similarMovies.length !== 0 && ( - <> - Recommendations + + Recommendations item.original_title} renderItem={({item}) => - - - {item.original_title} - + } - /> + /> )} {review.length !== 0 && ( - <> - Commentaires + + Commentaires item.pseudo} renderItem={({item}) => - - - - - - {item.pseudo} - {item.date} - - - - - {item.message} - + } - /> + /> )} @@ -287,13 +487,3 @@ export default function InfoScreen({navigation, route}: RootStackScreenProps<'In ) } -type InfoBadgeProps = { - texte: string - -} - -export function InfoBadge(props: InfoBadgeProps) { - return ( - {props.texte} - ); -} \ No newline at end of file diff --git a/screens/WatchLaterScreen.tsx b/screens/WatchLaterScreen.tsx index c5dad4a..b6dbaaa 100644 --- a/screens/WatchLaterScreen.tsx +++ b/screens/WatchLaterScreen.tsx @@ -1,26 +1,49 @@ import {FlatList, StyleSheet, SafeAreaView, Text, View, Image, TextInput, TouchableHighlight} from 'react-native'; import * as React from "react"; -import {BadgeFilm, Stars} from "./HomeScreen"; import {FontAwesomeIcon} from "@fortawesome/react-native-fontawesome"; import {faClock} from "@fortawesome/free-solid-svg-icons"; import {RootTabScreenProps} from "../types"; import {useSafeAreaInsets} from "react-native-safe-area-context"; import {useDispatch, useSelector} from 'react-redux'; import {useEffect, useState} from 'react'; -import {getTrendingID, getWatchLater, getWatchLaterMovies} from "../redux/actions/actionGetTrendingID"; +import {getWatchLater} from "../redux/actions/actionGetTrendingID"; import Movie from "../model/Movie"; -import {useNavigation} from "@react-navigation/native"; -import {LinearGradient} from 'expo-linear-gradient'; +import {MovieListComponent} from "../components/MovieListComponent"; export default function WatchLaterScreen({navigation}: RootTabScreenProps<'WatchLater'>) { + const [search, setSearch] = useState(''); + const [filteredDataSource, setFilteredDataSource] = useState([]); - const [masterDataSource, setMasterDataSource] = useState([]); + + const [masterDataSource] = useState([]); + const insets = useSafeAreaInsets(); + const searchFilterFunction = (text: string) => { + if (text) { + const newData = watchLaterMovies.filter(function (item: Movie) { + const itemData = item.original_title + ? item.original_title.toUpperCase() + : ''.toUpperCase(); + const textData = text.toUpperCase(); + return itemData.indexOf(textData) > -1; + }); + setFilteredDataSource(newData); + setSearch(text); + } else { + setFilteredDataSource(masterDataSource); + setSearch(text); + } + }; + // @ts-ignore + const watchLaterMovies = useSelector(state => state.appReducer.watchLaterMovies); + + const dispatch = useDispatch(); + const styles = StyleSheet.create({ container: { flex: 1, - paddingTop: 22, + paddingTop: insets.top + 22, backgroundColor: "#0E0E0E" }, linearGradient: { @@ -40,136 +63,73 @@ export default function WatchLaterScreen({navigation}: RootTabScreenProps<'Watch height: 100, borderRadius: 8, }, + searchSection: { + height: 40, + width: 400, + backgroundColor: "grey", + borderRadius: 20, + marginVertical: 10, + alignSelf: "center" + }, + searchBar: { + width: '100%', + height: 40, + marginHorizontal: 20 + }, + titlePage: { + height: 50, + justifyContent: "flex-start", + flexDirection: 'row', + paddingHorizontal: 20, + marginBottom: 15, + marginVertical: 5, + alignItems: "flex-end" + }, + icon: { + marginBottom: -5, + marginRight: 20 + }, + delimiter: { + height: 2, + width: 400, + resizeMode: "stretch" + }, + h1: { + color: "white", + fontSize: 30 + } }); - const dispatch = useDispatch(); - // @ts-ignore - const watchLaterMovies = useSelector(state => state.appReducer.watchLaterMovies); + useEffect(() => { const loadWatchLater = async () => { // @ts-ignore await dispatch(getWatchLater()); }; - console.log("test11111:", watchLaterMovies); loadWatchLater(); }, [dispatch]); - const searchFilterFunction = (text: string) => { - if (text) { - const newData = watchLaterMovies.filter(function (item: Movie) { - const itemData = item.original_title - ? item.original_title.toUpperCase() - : ''.toUpperCase(); - const textData = text.toUpperCase(); - return itemData.indexOf(textData) > -1; - }); - setFilteredDataSource(newData); - setSearch(text); - } else { - setFilteredDataSource(masterDataSource); - setSearch(text); - } - }; return ( - - - Watch Later + + + Watch Later - - searchFilterFunction(text)} + + searchFilterFunction(text)} value={search} > item.original_title} - renderItem={({item}) => navigation.navigate("Info", {"item": item})}>} + // @ts-ignore + renderItem={({item}) => navigation.navigate("Info", {"item": item})}>} /> ); } - -type ListWidgetProps = { - movie: Movie - -} - -export function ListWidget(props: ListWidgetProps) { - const insets = useSafeAreaInsets(); - - const styles = StyleSheet.create({ - filmCard: { - width: 70, - height: 110, - borderRadius: 8, - - - }, - }); - - function formatTime(time: number) { - console.log(time); - const hours = Math.floor(time / 60); - const minutes = time % 60; - return `${hours}h ${minutes < 10 ? `0${minutes}` : minutes}m`; - } - - return ( - - - - - - - {props.movie.original_title} - - - - {props.movie.vote_average.toFixed(1)} - - - {formatTime(props.movie.runtime)} - - {props.movie.overview} - - - - ); -} \ No newline at end of file