Code clean 🎉

Tests
Lucas Delanier 2 years ago
parent b80ad6d113
commit f0154a514c

@ -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 (<View style={{flexDirection: 'column', alignSelf: 'center', paddingHorizontal: 30, width: '100%', alignItems: "center", paddingTop: 10, flex: 0.07}}>
<Text numberOfLines={1} style={{color: "white", fontSize: 30, fontWeight: "bold", paddingTop: 5, alignSelf: "center"}}>{props.movie.original_title}</Text>
<View style={{flexDirection: 'row', justifyContent: "center", alignItems: "center", alignSelf: "center"}}>
<Text style={{color: "#D1D1D1", fontSize: 20, fontWeight: "normal", paddingTop: 5}}>{`${props.movie.release_date}`}</Text>
<View style={styles.circle}/>
<Text style={{color: "#D1D1D1", fontSize: 20, fontWeight: "normal", paddingTop: 5}}>{`${props.movie.genres[0]} ${props.movie.genres[1] !== undefined ? ", " + props.movie.genres[1] : ""}`}</Text>
<View style={styles.circle}/>
<Text style={{color: "#D1D1D1", fontSize: 20, fontWeight: "normal", paddingTop: 5}}>{`${formatTime(props.movie.runtime)}`}</Text>
</View>
<Stars note={props.movie.vote_average} size={110}/>
</View>);
}

@ -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 (
<LinearGradient style={styles.body} start={{x: 0, y: 1}}
end={{x: 1, y: 1}}
// Button Linear Gradient
colors={['#0B0B0B', '#1F1F1F']}>
<Image
style={styles.filmCard}
source={{
uri: props.movie.poster_path_min,
}}
/>
<View style={styles.section}>
<Text numberOfLines={1} style={styles.h1}>{props.movie.original_title}</Text>
<View style={styles.infoSection}>
<View style={styles.top}>
<Stars note={props.movie.vote_average} size={90}></Stars>
<Text style={styles.vote}>{props.movie.vote_average.toFixed(1)}</Text>
</View>
<Text style={styles.h3}>{formatTime(props.movie.runtime)}</Text>
</View>
<Text numberOfLines={3} style={{color: "#C7C7C7", fontWeight: "600",}}>{props.movie.overview}</Text>
</View>
</LinearGradient>
);
}

@ -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 (
<View>
<Image source={imageSource} style={{
width: props.size,
height: 40,
resizeMode: 'contain'
}}/>
</View>
);
};
export default Stars;

@ -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 (
<View style={{zIndex: 1, alignContent: "center", justifyContent: "center", flex: 0.15, flexDirection: "row"}}>
<Text style={{color: "#FFF", fontSize: 16, fontWeight: "500"}}>Nouvelle collection dans</Text>
<Image source={require('../assets/images/timer_icon.png')} style={{
height: 30,
resizeMode: 'contain',
top: -5
}}></Image>
<Text style={{color: "#FFF", fontSize: 16, fontWeight: "500"}}>{`${props.hours.toString().padStart(2, '0')}:`}</Text>
<Text style={{color: "#FFF", fontSize: 16, fontWeight: "500"}}>{`${props.minutes.toString().padStart(2, '0')}:`}</Text>
<Text style={{color: "#FFF", fontSize: 16, fontWeight: "500"}}>{`${props.seconds.toString().padStart(2, '0')}`}</Text>
</View>
);
}
export function Timer2(props: TimerProps) {
return (
<View style={{zIndex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 20, paddingVertical: 10, borderRadius: 100, flexDirection: "row", bottom: 0, backgroundColor: "white", marginTop: 50}}>
<Text style={{color: "black", fontSize: 16, fontWeight: "500"}}>Nouvelle collection dans</Text>
<Image source={require('../assets/images/timer_icon2.png')} style={{
height: 30,
resizeMode: 'contain', marginHorizontal: 7
}}></Image>
<Text style={{color: "black", fontSize: 16, fontWeight: "500"}}>{`${props.hours.toString().padStart(2, '0')}:`}</Text>
<Text style={{color: "black", fontSize: 16, fontWeight: "500"}}>{`${props.minutes.toString().padStart(2, '0')}:`}</Text>
<Text style={{color: "black", fontSize: 16, fontWeight: "500"}}>{`${props.seconds.toString().padStart(2, '0')}`}</Text>
</View>
);
}

@ -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;

@ -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);

@ -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);
}
}
}

@ -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;
}

@ -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<Movie[]>([]);
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 (
<SafeAreaView style={styles.container}>
<View style={{height: 50, justifyContent: "flex-start",flexDirection: 'row', paddingHorizontal:20, marginBottom: 15,marginVertical:5, alignItems:"flex-end"}} >
<FontAwesomeIcon icon={faHeart} style={{marginBottom: -5, marginRight: 20}} size={50} color="white" />
<Text style={{color: "white", fontSize:30}}>Favorite</Text>
<View style={styles.titlePage}>
<FontAwesomeIcon icon={faClock} style={styles.icon} size={50} color="white"/>
<Text style={styles.h1}>Watch Later</Text>
</View>
<Image
source={require('../assets/images/delimiter.png')} style={{height: 2, width: 400, resizeMode: "stretch"}}
source={require('../assets/images/delimiter.png')} style={styles.delimiter}
/>
<View style={{height:40, width:400, backgroundColor:"grey", borderRadius:20, marginVertical:10, alignSelf:"center"}}>
<TextInput style={{width: '100%', height: 40, marginHorizontal: 20}} onChangeText={(text) => searchFilterFunction(text)}
<View style={styles.searchSection}>
<TextInput style={styles.searchBar} onChangeText={(text) => searchFilterFunction(text)}
value={search}
></TextInput>
</View>
<FlatList
data={search.length !== 0 ? filteredDataSource : favouriteMovies}
keyExtractor={item => item.original_title}
renderItem={({item}) => <ListWidget movie={item}></ListWidget>}
// @ts-ignore
renderItem={({item}) => <TouchableHighlight onPress={() => navigation.navigate("Info", {"item": item})}><MovieListComponent movie={item}></MovieListComponent></TouchableHighlight>}
/>
</SafeAreaView>
);
}
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 (
<View style={{
height: 130,
width: "100%",
borderRadius: 20,
justifyContent: "flex-start",
flexDirection: 'row',
marginHorizontal: 20,
marginBottom: 15
}}>
<Image
style={styles.filmCard}
source={{
uri: props.movie.poster_path,
}}
/>
<View style={{
height: 130,
width: "70%",
justifyContent: "center",
flexDirection: 'column',
paddingRight: 20,
paddingLeft: 20,
}}>
<Text numberOfLines={1} style={{
color: "white",
fontWeight: "700",
fontSize: 21,
}}>{props.movie.original_title}</Text>
<View style={{flexDirection: "row", alignItems: "center", justifyContent: "space-between", width: "100%"}}>
<View style={{flexDirection: "row", alignItems: "center",}}>
<Stars note={props.movie.vote_average} size={70}></Stars>
<Text style={{paddingLeft: 10, color: "white", fontWeight: "bold"}}>{props.movie.vote_average.toFixed(1)}</Text>
</View>
<Text style={{color: "grey", fontWeight: "600"}}>{formatTime(props.movie.runtime)}</Text>
</View>
<Text numberOfLines={3} style={{color: "grey", fontWeight: "600",}}>{props.movie.overview}</Text>
</View>
</View>
);
}

@ -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 (
<>
<ImageBackground blurRadius={0}
style={{
width: "110%",
height: "110%",
justifyContent: "center",
alignItems: "center",
opacity: 0.15,
position: "absolute",
zIndex: 0
}}
style={styles.finishBackground}
source={require("../assets/images/background.png")
}
></ImageBackground>
@ -188,32 +197,12 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) {
<ImageBackground blurRadius={29}
style={{
width: "150%",
height: "150%",
justifyContent: "center",
alignItems: "center",
opacity: 0.55,
position: 'absolute',
left: "-50%",
top: "-50%"
}}
style={styles.posterBackground}
source={{
uri: trendingMovies[displayIndex]?.poster_path,
}}
></ImageBackground>
<View style={{flexDirection: 'column', alignSelf: 'center', paddingHorizontal: 30, width: '100%', alignItems: "center", paddingTop: 10, flex: 0.07}}>
<Text numberOfLines={1} style={{color: "white", fontSize: 30, fontWeight: "bold", paddingTop: 5, alignSelf: "center"}}>{trendingMovies[displayIndex].original_title}</Text>
<View style={{flexDirection: 'row', justifyContent: "center", alignItems: "center", alignSelf: "center"}}>
<Text style={{color: "#D1D1D1", fontSize: 20, fontWeight: "normal", paddingTop: 5}}>{`${trendingMovies[displayIndex].release_date}`}</Text>
<View style={styles.circle}/>
<Text style={{color: "#D1D1D1", fontSize: 20, fontWeight: "normal", paddingTop: 5}}>{`${trendingMovies[displayIndex].genres[0]} ${trendingMovies[displayIndex].genres[1] !== undefined ? ", " + trendingMovies[0].genres[1] : ""}`}</Text>
<View style={styles.circle}/>
<Text style={{color: "#D1D1D1", fontSize: 20, fontWeight: "normal", paddingTop: 5}}>{`${formatTime(trendingMovies[displayIndex].runtime)}`}</Text>
</View>
<Stars note={trendingMovies[displayIndex].vote_average} size={110}/>
</View>
<HeaderMovie movie={trendingMovies[displayIndex]}></HeaderMovie>
<CardsSwipe
ref={(rf) => {
@ -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'>) {
/>
<View style={{flexDirection: 'row', alignItems: 'flex-end', justifyContent: "space-evenly", paddingHorizontal: 30, width: '100%', position: "absolute", top: "74%", zIndex: 30}}>
<View style={styles.buttonSection}>
<TouchableOpacity onPress={() => {
addWatchLater(trendingMovies[displayIndex]);
@ -259,7 +247,7 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) {
}}>
<Image
source={require('../assets/images/watchlater_button.png')} style={{resizeMode: "stretch", height: '55%', aspectRatio: 1,}}
source={require('../assets/images/watchlater_button.png')} style={styles.button}
/>
</TouchableOpacity>
<TouchableOpacity onPress={
@ -267,9 +255,7 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) {
popFirstTrending(trendingMovies[displayIndex]);
}}>
<Image
source={require('../assets/images/delete_button.png')} style={{
resizeMode: "stretch", height: '55%', aspectRatio: 1,
}}
source={require('../assets/images/delete_button.png')} style={styles.button}
/>
</TouchableOpacity>
@ -278,45 +264,24 @@ export default function HomeScreen({navigation}: RootStackScreenProps<'Home'>) {
}
}>
<Image
source={require('../assets/images/like_button.png')} style={{resizeMode: "stretch", height: '55%', aspectRatio: 1,}}
source={require('../assets/images/like_button.png')} style={styles.button}
/>
</TouchableOpacity>
</View>
<View style={{zIndex: 1, alignContent: "center", justifyContent: "center", flex: 0.15, flexDirection: "row"}}>
<Text style={{color: "#FFF", fontSize: 16, fontWeight: "500"}}>Nouvelle collection dans</Text>
<Image source={require('../assets/images/timer_icon.png')} style={{
height: 30,
resizeMode: 'contain',
top: -5
}}></Image>
<Text style={{color: "#FFF", fontSize: 16, fontWeight: "500"}}>{`${hours.toString().padStart(2, '0')}:`}</Text>
<Text style={{color: "#FFF", fontSize: 16, fontWeight: "500"}}>{`${minutes.toString().padStart(2, '0')}:`}</Text>
<Text style={{color: "#FFF", fontSize: 16, fontWeight: "500"}}>{`${seconds.toString().padStart(2, '0')}`}</Text>
</View>
<Timer hours={hours} minutes={minutes} seconds={seconds}></Timer>
</SafeAreaView>)}
{trendingMovies.length === 0 && (
<SafeAreaView style={styles.background2}>
<View style={{alignItems: "center", width: "100%", height: "100%", justifyContent: "center", zIndex: 1}}>
<Text style={{color: "white", fontWeight: "600", fontSize: 35}}>Félicitations !</Text>
<View style={styles.congratsSection}>
<Text style={styles.h1}>Félicitations !</Text>
<AnimatedLottieView source={require("../assets/animation.json")} autoPlay={true} loop={true} style={{height: 200}}/>
<Text style={{color: "grey", fontWeight: "400", paddingHorizontal: 70, textAlign: "center"}}>Vous avez fini la collection du jour.
<Text style={styles.explanation}>Vous avez fini la collection du jour.
{"\n"}Revenez à la fin du décompte pour découvrir de nouvelles propositions.</Text>
<View style={{zIndex: 1, alignItems: "center", justifyContent: "center", paddingHorizontal: 20, paddingVertical: 10, borderRadius: 100, flexDirection: "row", bottom: 0, backgroundColor: "white", marginTop: 50}}>
<Text style={{color: "black", fontSize: 16, fontWeight: "500"}}>Nouvelle collection dans</Text>
<Image source={require('../assets/images/timer_icon2.png')} style={{
height: 30,
resizeMode: 'contain', marginHorizontal: 7
}}></Image>
<Text style={{color: "black", fontSize: 16, fontWeight: "500"}}>{`${hours.toString().padStart(2, '0')}:`}</Text>
<Text style={{color: "black", fontSize: 16, fontWeight: "500"}}>{`${minutes.toString().padStart(2, '0')}:`}</Text>
<Text style={{color: "black", fontSize: 16, fontWeight: "500"}}>{`${seconds.toString().padStart(2, '0')}`}</Text>
</View>
<Timer2 hours={hours} minutes={minutes} seconds={seconds}></Timer2>
</View>
</SafeAreaView>
@ -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 (
<View style={{paddingHorizontal: 20, marginHorizontal: 5, height: 35, backgroundColor: '#2E2E2E', borderRadius: 20, justifyContent: "center"}}>
<Text style={{color: "white"}}>{props.name}</Text>
</View>
);
} else {
return (
<View style={{paddingHorizontal: 20, marginHorizontal: 5, height: 35, backgroundColor: '#5C5C5C', borderRadius: 20, borderWidth: 1, borderColor: "white", justifyContent: "center"}}>
<Text style={{color: "white"}}>{props.name}</Text>
</View>
);
}
}
type BadgeFilmProps = {
name: String
}
export function BadgeFilm(props: BadgeFilmProps) {
return (
<View style={{
paddingHorizontal: 15,
marginHorizontal: 5,
height: 30,
backgroundColor: '#8906B8',
borderRadius: 15,
justifyContent: "center",
alignSelf: "flex-start"
}}>
<Text style={{color: "white", fontSize: 12, fontWeight: "bold"}}>{props.name}</Text>
</View>
);
}
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 (
<View>
<Image source={imageSource} style={{
width: props.size,
height: 40,
resizeMode: 'contain'
}}/>
</View>
);
};

@ -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<MinimalMovie[]>([]);
const [review, setReview] = useState<Review[]>([]);
const [credit, setCredit] = useState<creditItem[]>();
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 }) => (
<View style={styles.creditContainer}>
<View style={styles.bubble}>
<Image source={{uri: item[1]}} style={styles.photo}></Image>
<View style={styles.popularityDot}>
<Text style={styles.popularityLabel}>{item[2].toFixed(1).toString()}</Text>
<Ionicons name="md-star" size={13} color="#FFC42D"/>
</View>
</View>
<Text numberOfLines={2} style={styles.creditName}>{item[0]}</Text>
</View>
);
return (
<FlatList
style={{paddingBottom: 40}}
data={data}
horizontal={true}
showsHorizontalScrollIndicator={false}
renderItem={renderItem}
keyExtractor={(item) => item[0]}
/>
);
}
type SimilarMovieProps = {
movie: minimalMovie;
};
function SimilarMovie(props: SimilarMovieProps) {
return (
<View style={styles.similarContainer}>
<Image source={{uri: props.movie.poster_path}} style={styles.similarPoster}></Image>
<Text numberOfLines={2} style={styles.similarTitleFilm}>{props.movie.original_title}</Text>
</View>
);
}
type ReviewProps = {
review: Review;
};
function ReviewComponent(props: ReviewProps) {
return (
<View style={styles.reviewContainer}>
<View style={styles.reviewInfo}>
<Image source={{uri: props.review.profile_path}} style={styles.imageProfile}></Image>
<View style={styles.infoContainer}>
<Text numberOfLines={1} style={styles.pseudo}>{props.review.pseudo}</Text>
<Text style={styles.date}>{props.review.date}</Text>
</View>
</View>
<Text numberOfLines={15} style={styles.message}>{props.review.message}</Text>
</View>
);
}
type InfoBadgeProps = {
texte: string
}
function InfoBadge(props: InfoBadgeProps) {
return (<View style={{paddingHorizontal: 15, paddingVertical: 7, backgroundColor: 'rgba(255,255,255,0.2)', borderRadius: 10, justifyContent: "center", marginRight: 10}}>
<Text style={{color: "white", fontSize: 15}}>{props.texte}</Text>
</View>);
}
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<MinimalMovie[]>([]);
const [review, setReview] = useState<Review[]>([]);
const [credit, setCredit] = useState<creditItem[]>();
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 }) => (
<View style={{width: 90, marginHorizontal: 7, alignItems: "center"}}>
<View style={{justifyContent: "center"}}>
<Image source={{uri: item[1]}} style={{height: 90, width: 90, borderRadius: 200, borderWidth: 3, borderColor: "rgba(255,255,255,0.8)"}}></Image>
<View style={{backgroundColor: "white", borderRadius: 20, padding: 2, paddingHorizontal: 5, justifyContent: "center", alignItems: "center", position: "absolute", bottom: 0, right: 0, flexDirection: "row"}}>
<Text style={{color: "black", fontWeight: "500", paddingRight: 4}}>{item[2].toFixed(1).toString()}</Text>
<Ionicons name="md-star" size={13} color="#FFC42D"/>
</View>
</View>
<Text numberOfLines={2} style={{color: "#DADADA", paddingTop: 5, fontWeight: "300"}}>{item[0]}</Text>
</View>
);
return (
<FlatList
style={{paddingBottom: 40}}
data={data}
horizontal={true}
showsHorizontalScrollIndicator={false}
renderItem={renderItem}
keyExtractor={(item) => item[0]}
/>
);
}
return (
<View style={{backgroundColor: "#0E0E0E"}}>
<View style={{height: "100%", width: "100%", position: "absolute"}}>
<View style={styles.body}>
<View style={styles.backgroundSection}>
<Image
style={{
height: "45%",
top: paddingtopbackgroud,
width: '100%',
opacity: opacitybackground,
position: "absolute",
transform: [{scale: scalebackground}],
}}
style={styles.back_drop}
source={{
uri: item.backdrop_path,
}}
@ -184,7 +410,7 @@ export default function InfoScreen({navigation, route}: RootStackScreenProps<'In
// Background Linear Gradient
colors={['rgba(0,0,0,0.8)', 'transparent']}
/>
<LinearGradient style={{height: "30%", top: "25%",}}
<LinearGradient style={styles.gradientFade}
// Button Linear Gradient
colors={['rgba(14,14,14,0)', 'rgba(14,14,14,0.7)', 'rgba(14,14,14,1)', 'rgba(14,14,14,1)']}>
</LinearGradient>
@ -193,90 +419,64 @@ export default function InfoScreen({navigation, route}: RootStackScreenProps<'In
<SafeAreaView style={styles.background1}>
<TouchableOpacity onPress={() => navigation.goBack()} style={{zIndex: 100}}>
<Ionicons name="ios-arrow-back" size={30} color="white" style={{position: "absolute", top: 10, left: 5}}/>
<Ionicons name="ios-arrow-back" size={30} color="white" style={styles.backButton}/>
</TouchableOpacity>
<ScrollView style={{height: "100%"}} showsVerticalScrollIndicator={false} onScroll={handleScroll} scrollEventThrottle={1}
<ScrollView style={styles.list} showsVerticalScrollIndicator={false} onScroll={handleScroll} scrollEventThrottle={1}
>
<View style={{paddingHorizontal: 35}}>
<Text style={{color: "white", fontSize: 43, fontWeight: "bold", paddingBottom: 10, paddingTop: "45%"}} numberOfLines={2}>{item.original_title}</Text>
<View style={{flexDirection: "row", width: "100%", justifyContent: "flex-start"}}>
<View style={styles.section1}>
<Text style={styles.title} numberOfLines={2}>{item.original_title}</Text>
<View style={styles.characteristics}>
<InfoBadge texte={`${item.genres[0]} ${item.genres[1] !== undefined ? ", " + item.genres[1] : ""}`}></InfoBadge>
<InfoBadge texte={item.release_date}></InfoBadge>
<InfoBadge texte={formatTime(item.runtime)}></InfoBadge>
</View>
<View style={{flexDirection: "row", width: "100%", justifyContent: "flex-start", alignItems: "center", paddingBottom: 30}}>
<View style={styles.stars}>
<Stars note={item.vote_average} size={120}></Stars>
<Text style={{color: "#FFC42D", fontWeight: "bold", paddingLeft: 10, fontSize: 16}}>{item.vote_average.toFixed(1)}</Text>
<Text style={styles.starsLabel}>{item.vote_average.toFixed(1)}</Text>
</View>
{trailerPath !== "" && (
<YoutubeIframe webViewStyle={{borderRadius: 10, overflow: "hidden"}}
height={195}
play={false}
videoId={trailerPath}
/>)}
<Text style={{color: "#B3B3B3", paddingTop: 30, fontSize: 17}}>{item.overview}</Text>
{trailerPath !== "" && (<YoutubeIframe webViewStyle={styles.player} height={195} play={false} videoId={trailerPath}/>)}
<Text style={styles.resume}>{item.overview}</Text>
</View>
{credit !== undefined && (
<>
<Text style={{color: "#2998FD", paddingTop: 30, paddingBottom: 20, paddingLeft: 35, fontSize: 17, fontWeight: "600"}}>Crédits</Text>
<CreditList data={credit}></CreditList></>
<View style={styles.creditSection}>
<Text style={styles.creditTitle}>Crédits</Text>
<CreditList data={credit}></CreditList>
</View>
)}
{similarMovies.length !== 0 && (
<>
<Text style={{color: "#2998FD", paddingTop: 30, paddingLeft: 35, fontSize: 17, fontWeight: "600"}}>Recommendations</Text>
<View style={styles.similarSection}>
<Text style={styles.similarTitle}>Recommendations</Text>
<FlatList
showsHorizontalScrollIndicator={false}
style={{paddingTop: 20}}
data={similarMovies}
horizontal={true}
keyExtractor={item => item.original_title}
renderItem={({item}) =>
<View style={{width: 90, marginHorizontal: 7}}>
<Image source={{uri: item.poster_path}} style={{height: 130, width: 90, borderRadius: 8}}></Image>
<Text numberOfLines={2} style={{color: "#DADADA", paddingTop: 5, fontWeight: "300"}}>{item.original_title}</Text>
</View>
<SimilarMovie movie={item}></SimilarMovie>
}
/></>
/></View>
)}
{review.length !== 0 && (
<>
<Text style={{color: "#2998FD", paddingTop: 30, paddingLeft: 35, fontSize: 17, fontWeight: "600"}}>Commentaires</Text>
<View style={styles.reviewSection}>
<Text style={styles.reviewTitle}>Commentaires</Text>
<FlatList
showsHorizontalScrollIndicator={false}
style={{paddingTop: 10}}
data={review}
horizontal={true}
keyExtractor={item => item.pseudo}
renderItem={({item}) =>
<View style={{marginHorizontal: 7, width: 300, padding: 20, backgroundColor: "#09090F", marginVertical: 10, borderRadius: 14, borderWidth: 0.8, borderColor: "rgba(223,223,223,0.14)"}}>
<View style={{flexDirection: "row", paddingBottom: 20}}>
<Image source={{uri: item.profil_path}} style={{height: 50, width: 50, borderRadius: 100}}></Image>
<View style={{paddingLeft: 10, flexDirection: "row", justifyContent: "space-between", width: "80%", alignItems: "center"}}>
<Text numberOfLines={1} style={{color: "white", paddingTop: 5, fontWeight: "700", fontSize: 16}}>{item.pseudo}</Text>
<Text style={{color: "grey", paddingTop: 5, fontWeight: "500", fontSize: 14}}>{item.date}</Text>
</View>
</View>
<Text numberOfLines={15} style={{color: "#B3B3B3", paddingTop: 5, fontWeight: "400"}}>{item.message}</Text>
</View>
<ReviewComponent review={item}></ReviewComponent>
}
/></>
/></View>
)}
@ -287,13 +487,3 @@ export default function InfoScreen({navigation, route}: RootStackScreenProps<'In
</View>
)
}
type InfoBadgeProps = {
texte: string
}
export function InfoBadge(props: InfoBadgeProps) {
return (<View style={{paddingHorizontal: 15, paddingVertical: 7, backgroundColor: 'rgba(255,255,255,0.2)', borderRadius: 10, justifyContent: "center", marginRight: 10}}>
<Text style={{color: "white", fontSize: 15}}>{props.texte}</Text>
</View>);
}

@ -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<Movie[]>([]);
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 (
<SafeAreaView style={styles.container}>
<View style={{height: 50, justifyContent: "flex-start", flexDirection: 'row', paddingHorizontal: 20, marginBottom: 15, marginVertical: 5, alignItems: "flex-end"}}>
<FontAwesomeIcon icon={faClock} style={{marginBottom: -5, marginRight: 20}} size={50} color="white"/>
<Text style={{color: "white", fontSize: 30}}>Watch Later</Text>
<View style={styles.titlePage}>
<FontAwesomeIcon icon={faClock} style={styles.icon} size={50} color="white"/>
<Text style={styles.h1}>Watch Later</Text>
</View>
<Image
source={require('../assets/images/delimiter.png')} style={{height: 2, width: 400, resizeMode: "stretch"}}
source={require('../assets/images/delimiter.png')} style={styles.delimiter}
/>
<View style={{height: 40, width: 400, backgroundColor: "grey", borderRadius: 20, marginVertical: 10, alignSelf: "center"}}>
<TextInput style={{width: '100%', height: 40, marginHorizontal: 20}} onChangeText={(text) => searchFilterFunction(text)}
<View style={styles.searchSection}>
<TextInput style={styles.searchBar} onChangeText={(text) => searchFilterFunction(text)}
value={search}
></TextInput>
</View>
<FlatList
data={search.length !== 0 ? filteredDataSource : watchLaterMovies}
keyExtractor={item => item.original_title}
renderItem={({item}) => <TouchableHighlight onPress={() => navigation.navigate("Info", {"item": item})}><ListWidget movie={item}></ListWidget></TouchableHighlight>}
// @ts-ignore
renderItem={({item}) => <TouchableHighlight onPress={() => navigation.navigate("Info", {"item": item})}><MovieListComponent movie={item}></MovieListComponent></TouchableHighlight>}
/>
</SafeAreaView>
);
}
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 (
<LinearGradient style={{
height: 130,
borderRadius: 20,
justifyContent: "flex-start",
flexDirection: 'row',
marginHorizontal: 10,
marginVertical: 7,
paddingHorizontal: 10,
backgroundColor: "#1D1D1D",
alignItems: "center",
borderWidth: 1.5,
borderColor: "#1F1F1F"
}} start={{x: 0, y: 1}}
end={{x: 1, y: 1}}
// Button Linear Gradient
colors={['#0B0B0B', '#1F1F1F']}>
<Image
style={styles.filmCard}
source={{
uri: props.movie.poster_path_min,
}}
/>
<View style={{
height: 130,
width: "85%",
justifyContent: "center",
flexDirection: 'column',
paddingRight: 20,
paddingLeft: 20,
}}>
<Text numberOfLines={1} style={{
color: "white",
fontWeight: "700",
fontSize: 21,
}}>{props.movie.original_title}</Text>
<View style={{flexDirection: "row", alignItems: "center", justifyContent: "space-between", width: "100%"}}>
<View style={{flexDirection: "row", alignItems: "center",}}>
<Stars note={props.movie.vote_average} size={90}></Stars>
<Text style={{paddingLeft: 7, color: "white", fontWeight: "bold", fontSize: 13}}>{props.movie.vote_average.toFixed(1)}</Text>
</View>
<Text style={{color: "grey", fontWeight: "600"}}>{formatTime(props.movie.runtime)}</Text>
</View>
<Text numberOfLines={3} style={{color: "#C7C7C7", fontWeight: "600",}}>{props.movie.overview}</Text>
</View>
</LinearGradient>
);
}
Loading…
Cancel
Save