Merge pull request 'part6' (#6) from part6 into master

Reviewed-on: #6
master
Antoine PEREDERII 1 year ago
commit 3cc455b3a5

@ -1,6 +1,4 @@
import {FlatList} from 'react-native';
import {SampleJoke} from "../model/SampleJoke";
import {CustomJoke} from "../model/CustomJoke";
import Categ from "./Categ";
import {Category} from "../model/Category";

@ -54,6 +54,7 @@ export default function JokeDetail(props: JokeItemProps) {
</View>
);
}
const styles = StyleSheet.create({
image : {
margin : 5,
@ -151,66 +152,3 @@ const styles = StyleSheet.create({
alignItems : 'center'
}
})
//
// const styles = StyleSheet.create({
// container: {
// marginHorizontal: "5%",
// display: "flex",
// marginBottom:7,
// marginTop:7,
// paddingVertical: 10,
// backgroundColor: indigoColor,
// justifyContent: 'space-between',
// borderRadius: 20,
// height: 500,
// borderColor: whiteColor,
// borderStyle: "solid",
// borderWidth: 1
// },
// row: {
// display: "flex",
// flexDirection:"row",
// alignSelf: "flex-end",
// },
// color: {
// flex: 0,
// backgroundColor: darksalmonColor,
// height: 150,
// width:15,
// },
// image: {
// width: '90%',
// alignSelf: "center",
// marginTop: 10,
// borderRadius: 5,
// // height: 500,
// backgroundColor: "red",
// flex: 1
// },
// columnContainer: {
// flexDirection: "column",
// marginLeft: 20,
// marginRight: 20,
// width: '60%',
// flex: 2,
// justifyContent: 'space-between',
// },
// text: {
// color:greyColor,
// paddingBottom: 7,
// paddingTop: 7,
// marginLeft: 19,
// fontSize: 16,
// },
// bottomContainer: {
// backgroundColor: whiteColor,
// paddingVertical: 5,
// paddingHorizontal: 10,
// margin: 10,
// marginLeft: 19,
// marginTop: 20,
// borderRadius: 20,
// width : 120,
// alignItems : 'center'
// }
// });

@ -1,9 +1,10 @@
import {FlatList, Text, TouchableHighlight} from 'react-native';
import {FlatList, Image, StyleSheet, Text, TouchableHighlight, TouchableOpacity, View} from 'react-native';
import {SampleJoke} from "../model/SampleJoke";
import {CustomJoke} from "../model/CustomJoke";
import JokeItem from "./JokeItem";
import React from "react";
import React, {useState} from "react";
import {useNavigation} from "@react-navigation/native";
import {darksalmonColor, greyColor, indigoColor, whiteColor} from "../assets/Theme";
type JokeListItemProps = {
jokes: (CustomJoke | SampleJoke)[];
@ -11,6 +12,9 @@ type JokeListItemProps = {
export default function JokeItems(props: JokeListItemProps) {
const navigation = useNavigation()
return (
<FlatList
data={props.jokes}
@ -26,3 +30,8 @@ export default function JokeItems(props: JokeListItemProps) {
/>
);
}
const styles = StyleSheet.create({
})

@ -21,7 +21,7 @@ export class CustomJoke extends Joke {
* @param {string} punchline - La chute de la blague.
* @param {string} image - L'URL de l'image associée à la blague.
*/
constructor(id: string, type: string, setup: string, punchline: string, image: string) {
constructor(id: string, type: string, setup: string, image: string, punchline: string = "") {
super(type, setup, punchline, image); // Assuming Joke class has these properties
this._id = id;
}

@ -65,7 +65,7 @@ export default function NavigationBar() {
/>
)
}}/>
<BottomTabNavigator.Screen name="Ajouter" component={Add}
<BottomTabNavigator.Screen name="Ajout d'une blague" component={Add}
options={{
tabBarIcon: ({focused}) => (
<View style={{backgroundColor: greyColor, borderRadius: 5, padding: 10}}>

@ -0,0 +1,19 @@
import {Category} from "../../model/Category";
export enum ActionType {
FETCH_CATEGORIES = 'FETCH_CATEGORIES',
}
type actionFetch = {
type: ActionType.FETCH_CATEGORIES;
payload: Category[];
}
export type Action = actionFetch;
export const setCategoriesList = (categoriesList: Category[]) => {
return {
type: ActionType.FETCH_CATEGORIES,
payload: categoriesList,
};
}

@ -0,0 +1,32 @@
import {CustomJoke} from "../../model/CustomJoke";
import {SampleJoke} from "../../model/SampleJoke";
export enum ActionType {
FETCH_JOKES = 'FETCH_JOKES',
POST_CUSTOM_JOKE = "POST_CUSTOM_JOKE",
}
type actionPostFetch = {
type: ActionType.POST_CUSTOM_JOKE;
payload: CustomJoke;
}
type actionGetFetch = {
type: ActionType.FETCH_JOKES;
payload: CustomJoke[];
}
export type Action = actionPostFetch | actionGetFetch;
export const setPostJoke = (customJoke: CustomJoke) => {
return {
type: ActionType.POST_CUSTOM_JOKE,
payload: customJoke
}
}
export const setCustomJokesList = (jokesList: CustomJoke[]) => {
return {
type: ActionType.FETCH_JOKES,
payload: jokesList,
};
}

@ -1,31 +1,20 @@
import {Category} from "../../model/Category";
import {SampleJoke} from "../../model/SampleJoke";
export enum ActionType {
FETCH_CATEGORIES = 'FETCH_CATEGORIES',
FETCH_JOKES = 'FETCH_JOKES',
FETCH_JOKES_BY_ID = 'FETCH_JOKES_BY_ID'
FETCH_JOKES_BY_ID = 'FETCH_JOKES_BY_ID',
}
type actionFetch = {
type: ActionType.FETCH_CATEGORIES;
payload: Category[];
} | {
type: ActionType.FETCH_JOKES;
payload: SampleJoke[];
} | {
}
type actionFetchById = {
type: ActionType.FETCH_JOKES_BY_ID;
payload: SampleJoke;
}
export type Action = actionFetch | actionFetchById;
export type Action = actionFetch;
export const setCategoriesList = (categoriesList: Category[]) => {
return {
type: ActionType.FETCH_CATEGORIES,
payload: categoriesList,
};
}
export const setJokesList = (jokesList: SampleJoke[]) => {
return {
type: ActionType.FETCH_JOKES,

@ -0,0 +1,24 @@
import {CustomJoke} from "../../model/CustomJoke";
import {SampleJoke} from "../../model/SampleJoke";
import {Action, ActionType} from "../actions/CategoryAction";
import {Category} from "../../model/Category";
interface State {
categories: Category[];
}
const initialState = {
categories: []
}
const categoryReducer = (state: State = initialState, action: Action) => {
switch (action.type) {
case ActionType.FETCH_CATEGORIES:
// @ts-ignore
return {...state, categories: action.payload};
default:
return state;
}
}
export default categoryReducer;

@ -0,0 +1,29 @@
import {CustomJoke} from "../../model/CustomJoke";
import {SampleJoke} from "../../model/SampleJoke";
import {Action, ActionType} from "../actions/CustomJoke";
import {Category} from "../../model/Category";
interface State {
customJokes: CustomJoke[];
customJoke: CustomJoke;
}
const initialState = {
customJokes: [],
customJoke: new CustomJoke('', '', '', '')
}
const customReducer = (state: State = initialState, action: Action) => {
switch (action.type) {
case ActionType.POST_CUSTOM_JOKE:
// @ts-ignore
return {...state, customJoke: action.payload};
case ActionType.FETCH_JOKES:
// @ts-ignore
return {...state, customJokes: action.payload};
default:
return state;
}
}
export default customReducer;

@ -1,31 +1,25 @@
import {CustomJoke} from "../../model/CustomJoke";
import {SampleJoke} from "../../model/SampleJoke";
import {Action} from "redux";
import {ActionType} from "../actions/JokeAction";
import {Action, ActionType} from "../actions/SampleAction";
import {Category} from "../../model/Category";
interface State {
categories: Category[];
jokes: SampleJoke[];
favoriteJokes: SampleJoke[];
joke : SampleJoke;
}
const initialState = {
categories: [],
jokes: [],
favoriteJokes: [],
joke: new SampleJoke(1, "", "", "", ""),
}
const appReducer = (state: State = initialState, action: Action) => {
const sampleReducer = (state: State = initialState, action: Action) => {
switch (action.type) {
case ActionType.FETCH_JOKES:
// @ts-ignore
return {...state, jokes: action.payload};
case ActionType.FETCH_CATEGORIES:
// @ts-ignore
return {...state, categories: action.payload};
case ActionType.FETCH_JOKES_BY_ID:
// @ts-ignore
return {...state, joke: action.payload}
@ -34,4 +28,4 @@ const appReducer = (state: State = initialState, action: Action) => {
}
}
export default appReducer;
export default sampleReducer;

@ -1,9 +1,13 @@
import {configureStore} from '@reduxjs/toolkit'
import appReducer from './reducers/jokeReducer';
import sampleReducer from "./reducers/SampleReducer";
import categoryReducer from "./reducers/CategoryReducer";
import customReducer from "./reducers/CustomReducer";
// Reference here all your application reducers
const reducer = {
appReducer: appReducer,
sampleReducer: sampleReducer,
categoryReducer: categoryReducer,
customReducer: customReducer,
}
// @ts-ignore

@ -0,0 +1,21 @@
import {SampleJoke} from "../../model/SampleJoke";
import { setJokeById} from "../actions/SampleAction";
export const getItem = <TItem>(uri:string, constructor : (json:any) => TItem, setItem: (item: TItem) => any) => {
//In order to use await your callback must be asynchronous using async keyword.
return async dispatch => {
//Then perform your asynchronous operations.
try {
const promise = await fetch(uri);
//Then use the json method to get json data from api/
const Json = await promise.json();
const Item: TItem = constructor(Json);
dispatch(setItem(Item));
} catch (error) {
console.log('Error---------', error);
}
}
}
export const getJokeById = (id) => {
return getItem<SampleJoke>('https://iut-weather-api.azurewebsites.net/jokes/samples/' + id , (elt) => new SampleJoke(elt["id"], elt["type"], elt["setup"], elt["image"]), (item) => setJokeById(item))
}

@ -1,6 +1,9 @@
import {SampleJoke} from "../../model/SampleJoke";
import {setCategoriesList, setJokeById, setJokesList} from "../actions/JokeAction";
import {setJokesList} from "../actions/SampleAction";
import {Category} from "../../model/Category";
import {setCategoriesList} from "../actions/CategoryAction";
import {CustomJoke} from "../../model/CustomJoke";
import {setCustomJokesList} from "../actions/CustomJoke";
export const getList = <TList>(uri:string, constructor : (json:any) => TList, setList: (list: TList[]) => any) => {
//In order to use await your callback must be asynchronous using async keyword.
@ -18,22 +21,6 @@ export const getList = <TList>(uri:string, constructor : (json:any) => TList, se
}
}
export const getItem = <TItem>(uri:string, constructor : (json:any) => TItem, setItem: (item: TItem) => any) => {
//In order to use await your callback must be asynchronous using async keyword.
return async dispatch => {
//Then perform your asynchronous operations.
try {
const promise = await fetch(uri);
//Then use the json method to get json data from api/
const Json = await promise.json();
const Item: TItem = constructor(Json);
dispatch(setItem(Item));
} catch (error) {
console.log('Error---------', error);
}
}
}
export const getLastSampleJokesList = () => {
return getList('https://iut-weather-api.azurewebsites.net/jokes/lasts', (elt) => new SampleJoke(elt["id"], elt["type"], elt["setup"], elt["image"]), (list) => setJokesList(list))
}
@ -46,6 +33,6 @@ export const getSampleJokesList = () => {
return getList('https://iut-weather-api.azurewebsites.net/jokes/samples', (elt) => new SampleJoke(elt["id"], elt["type"], elt["setup"], elt["image"]), (list) => setJokesList(list))
}
export const getJokeById = (id) => {
return getItem<SampleJoke>('https://iut-weather-api.azurewebsites.net/jokes/samples/' + id , (elt) => new SampleJoke(elt["id"], elt["type"], elt["setup"], elt["image"]), (item) => setJokeById(item))
export const getCustomJokesList = () => {
return getList('https://iut-weather-api.azurewebsites.net/jokes', (elt) => new CustomJoke(elt["id"], elt["type"], elt["setup"], elt["image"]), (list) => setCustomJokesList(list))
}

@ -0,0 +1,44 @@
import {setPostJoke} from "../actions/CustomJoke";
import {SampleJoke} from "../../model/SampleJoke";
import {setJokesList} from "../actions/SampleAction";
import {getList} from "./GetThunk";
export const setItem = <TItem>(
uri: string,
type : string,
setup : string,
punchline : string
) => {
return async dispatch => {
try {
// @ts-ignore
const response = await fetch(uri, {
method: 'POST',
headers: {
Accept: "application/json",
"Content-Type": 'application/json',
},
body: JSON.stringify(
{
type: type,
setup: setup,
punchline: punchline
}
)
});
const data = await response.json();
dispatch(setPostJoke(data));
if (response.ok) {
console.log('Envoie ok de custom joke')
} else {
console.log('Erreur lors de la requête POST');
}
} catch (error) {
console.log('Erreur :', error);
}
};
};
export const postCustomJoke = (joke, downgrade, category) => {
return setItem('https://iut-weather-api.azurewebsites.net/jokes', joke, downgrade, category)
}

@ -3,32 +3,181 @@ import { sampleJokeStub } from '../data/stub/SampleJokeStub';
import JokeItems from "../components/JokeItems";
import '../types/extension';
import {useDispatch, useSelector} from "react-redux";
import {StyleSheet, View} from "react-native";
import {purpleColor} from "../assets/Theme";
import {getSampleJokesList} from "../redux/thunk/RecentsJokesThunk";
import {useEffect} from "react";
import {Image, StyleSheet, Text, TextInput, TouchableOpacity, View} from "react-native";
import {darksalmonColor, greyColor, indigoColor, purpleColor, whiteColor} from "../assets/Theme";
import {getSampleJokesList} from "../redux/thunk/GetThunk";
import React, {useEffect} from "react";
import {postCustomJoke} from "../redux/thunk/PostThunk";
export default function Catalogue() {
export default function AddScreen() {
// @ts-ignore
const allJokes = useSelector(state => state.appReducer.jokes);
const allJokes = useSelector(state => state.customReducer.jokes);
const dispatch = useDispatch();
const MAX_LENGTH = 10;
const [joke, onChangeJoke] = React.useState('');
const [downgrade, onChangeDowngrade] = React.useState('');
const [category, onChangeCategory] = React.useState('');
useEffect(() => {
const loadJokes = async () => {
const clearFields = () => {
onChangeCategory('');
onChangeJoke('');
onChangeDowngrade('');
}
const handleCreate = () => {
// @ts-ignore
await dispatch(getSampleJokesList());
dispatch(postCustomJoke(joke, downgrade, category));
clearFields();
};
loadJokes();
}, [dispatch]);
// const [joke, setJoke] = useState("");
// const [jokeFall, setJokeFall] = useState("");
// const [category, setCategory] = useState("");
// const [categoryExceeded, setCategoryExceeded] = useState(false);
// const [buttonDisabled, setButtonDisabled] = useState(true);
// const MAX_CATEGORY_LENGTH = 10;
// const dispatch = useDispatch();
// useEffect(() => {
// if (joke !== "" && jokeFall !== "" && category !== "") {
// setButtonDisabled(false);
// } else {
// setButtonDisabled(true);
// }
// }, [joke, jokeFall, category]);
// const postjoke = async () => {
// // @ts-ignore
// await dispatch(postJoke(joke, jokeFall, category));
// clearFields();
// };
//
// const clearFields = () => {
// setJoke("");
// setJokeFall("");
// setCategory("");
// setCategoryExceeded(false);
// setButtonDisabled(true);
// };
// const handleCategoryChange = (text) => {
// if (text.length > MAX_CATEGORY_LENGTH) {
// setCategoryExceeded(true);
// } else {
// setCategoryExceeded(false);
// setCategory(text);
// }
// };
return (
<View style={styles.container}>
<JokeItems jokes={allJokes}/>
<Text style={styles.text}>Blague</Text>
<TextInput
style={styles.textInput}
onChangeText={onChangeJoke}
value={joke}
placeholder="Inserez votre blague"
placeholderTextColor={whiteColor}
scrollEnabled={true}
autoCorrect={true}
multiline={true}
numberOfLines={10}
cursorColor={indigoColor}
/>
<Text style={styles.text}>Chute de la blague</Text>
<TextInput
style={styles.textInput}
onChangeText={onChangeDowngrade}
value={downgrade}
multiline={true}
placeholder="Inserez votre blague"
placeholderTextColor={whiteColor}
scrollEnabled={true}
autoCorrect={true}
numberOfLines={10}
cursorColor={indigoColor}
/>
<Text style={styles.text}>Catégorie</Text>
<TextInput
style={styles.textInput}
onChangeText={onChangeCategory}
value={category}
placeholder="Inserez votre blague"
placeholderTextColor={whiteColor}
scrollEnabled={true}
autoCorrect={true}
maxLength={10}
cursorColor={indigoColor}
/>
<View style={styles.viewCounter}>
<Text style={styles.textSize}>{category.length}/{MAX_LENGTH}</Text>
</View>
<TouchableOpacity style={styles.createButton} onPress={handleCreate}>
<Text style={styles.createTextButton} >CRÉER</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.eraseButton} onPress={clearFields}>
<Text style={styles.eraseTextButton} >EFFACER</Text>
</TouchableOpacity>
</View>
)
};
const styles = StyleSheet.create({
container: {
backgroundColor: purpleColor
backgroundColor: purpleColor,
width: "100%",
height: "100%",
},
textInput: {
backgroundColor: indigoColor,
color: whiteColor,
width: "90%",
alignSelf:"center",
minHeight: 100
},
eraseButton:{
borderRadius : 5,
alignItems: "center",
backgroundColor : whiteColor,
height:50,
margin: 10
},
createButton:{
borderRadius : 5,
alignItems: "center",
backgroundColor : darksalmonColor,
height:50,
margin: 10,
marginTop: 30
},
createTextButton : {
margin: 10,
textAlign : "center",
fontWeight: "700",
color : whiteColor,
},
eraseTextButton : {
margin: 10,
textAlign : "center",
fontWeight: "700",
color : darksalmonColor,
},
text: {
color:whiteColor,
paddingBottom: 10,
paddingTop: 25,
marginLeft: 19,
fontSize: 20,
},
textSize: {
paddingTop: 15,
marginRight: 19,
fontSize: 12,
color: whiteColor,
},
viewCounter: {
alignItems: 'flex-end',
bottom: 10,
right: 10,
}
});
})

@ -1,27 +1,57 @@
import JokeItems from "../components/JokeItems";
import '../types/extension';
import {StyleSheet, View} from "react-native";
import {purpleColor} from "../assets/Theme";
import {Image, SafeAreaView, StyleSheet, Text, TouchableOpacity, View} from "react-native";
import {darksalmonColor, purpleColor, whiteColor} from "../assets/Theme";
import {useDispatch, useSelector} from "react-redux";
import {useEffect} from "react";
import { getSampleJokesList } from "../redux/thunk/RecentsJokesThunk";
import React, {useEffect, useState} from "react";
import {getCustomJokesList, getSampleJokesList} from "../redux/thunk/GetThunk";
export default function Catalogue() {
// @ts-ignore
const allJokes = useSelector(state => state.appReducer.jokes);
const sampleJokes = useSelector(state => state.sampleReducer.jokes);
// @ts-ignore
const customJokes = useSelector(state => state.customReducer.customJoke);
const dispatch = useDispatch();
useEffect(() => {
const loadJokes = async () => {
const loadSamplesJokes = async () => {
// @ts-ignore
await dispatch(getSampleJokesList());
};
loadJokes();
loadSamplesJokes();
}, [dispatch]);
const loadCustomJokes = async () => {
// @ts-ignore
await dispatch(getCustomJokesList());
};
const [showCustomJoke, setCustomJoke] = useState(false); // état local pour contrôler la visibilité de la description
const toggleDescription = () => {
setCustomJoke(!showCustomJoke);
loadCustomJokes();
};
const eye = require("../assets/eye_icon.png")
const hideEye = require("../assets/eye_off_icon.png")
return (
<SafeAreaView style={styles.container}>
<View style={styles.columnContainer}>
<Text style={styles.TextButton}>Afficher les exemples</Text>
<TouchableOpacity style={styles.Button} onPress={toggleDescription}>
<View style={styles.jokeTypeContainer}>
<Image
source={showCustomJoke ? hideEye : eye}
style={styles.imageButton}
/>
</View>
</TouchableOpacity>
</View>
<View style={styles.container}>
<JokeItems jokes={allJokes}/>
<JokeItems jokes={showCustomJoke ? customJokes : sampleJokes}/>
</View>
</SafeAreaView>
)
};
@ -29,5 +59,44 @@ const styles = StyleSheet.create({
container: {
backgroundColor: purpleColor,
flex:1,
},
Button:{
borderRadius : 5,
backgroundColor : darksalmonColor,
height:40,
width : 60,
flexDirection : "row"
},
jokeTypeContainer :{
display : "flex",
flex : 1,
flexDirection: "row",
alignItems : "center"
},
imageButton : {
margin : 10,
width: 40,
height:30,
top : 5,
alignSelf : "center",
backgroundColor: "none",
tintColor : whiteColor,
justifyContent: "center",
alignItems: "center",
},
TextButton : {
fontSize: 18,
color: whiteColor,
textAlign: 'center',
fontWeight: 'bold',
margin: 10,
},
columnContainer: {
marginLeft: 20,
marginRight: 20,
width: '90%',
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
}
});

@ -5,13 +5,15 @@ import JokesHomeSquare from "../components/JokesHomeSquare";
import Categs from "../components/Categs";
import {useDispatch, useSelector} from "react-redux";
import {useEffect} from "react";
import {getCategoriesList, getLastSampleJokesList} from "../redux/thunk/RecentsJokesThunk";
import {getCategoriesList, getLastSampleJokesList} from "../redux/thunk/GetThunk";
import SampleReducer from "../redux/reducers/SampleReducer";
import CategoryReducer from "../redux/reducers/CategoryReducer";
export default function Catalogue() {
// @ts-ignore
const allJokes = useSelector(state => state.appReducer.jokes);
const allJokes = useSelector(state => state.sampleReducer.jokes);
// @ts-ignore
const allCategories = useSelector(state => state.appReducer.categories)
const allCategories = useSelector(state => state.categoryReducer.categories);
const dispatch = useDispatch();
useEffect(() => {

@ -3,13 +3,13 @@ import {StyleSheet, View} from "react-native";
import {purpleColor} from "../assets/Theme";
import {useDispatch, useSelector} from "react-redux";
import React, {useEffect} from "react";
import { getJokeById } from "../redux/thunk/RecentsJokesThunk";
import { getJokeById } from "../redux/thunk/GetByThunk";
import JokeDetail from "../components/JokeDetail";
export default function JokeDetailsScreen({route}) {
const idJokeDetail = route.params.idJoke;
// @ts-ignore
const joke = useSelector(state => state.appReducer.joke);
const joke = useSelector(state => state.sampleReducer.joke);
const dispatch = useDispatch();
useEffect(() => {

Loading…
Cancel
Save