commit
6bd58278a0
@ -1,5 +1,32 @@
|
|||||||
|
import {Theme} from "@react-navigation/native";
|
||||||
|
|
||||||
export const indigoColor = "rgba(14, 14, 44, 1)";
|
export const indigoColor = "rgba(14, 14, 44, 1)";
|
||||||
export const purpleColor = "rgba(74, 74, 104, 1)";
|
export const purpleColor = "rgba(74, 74, 104, 1)";
|
||||||
export const darksalmonColor = "rgba(233, 150, 122, 1)";
|
export const darksalmonColor = "rgba(233, 150, 122, 1)";
|
||||||
export const greyColor = "rgba(140, 140, 161, 1)";
|
export const greyColor = "rgba(140, 140, 161, 1)";
|
||||||
export const whiteColor = "rgba(239, 239, 253, 1)";
|
export const whiteColor = "rgba(239, 239, 253, 1)";
|
||||||
|
|
||||||
|
|
||||||
|
export const DefaultTheme: Theme = {
|
||||||
|
dark: false,
|
||||||
|
colors: {
|
||||||
|
primary: 'rgb(0, 122, 255)',
|
||||||
|
background: "rgba(239, 239, 253, 1)",
|
||||||
|
card: 'rgb(255, 255, 255)',
|
||||||
|
text: 'rgb(28, 28, 30)',
|
||||||
|
border: 'rgb(216, 216, 216)',
|
||||||
|
notification: 'rgb(255, 59, 48)',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DarkTheme: Theme = {
|
||||||
|
dark: true,
|
||||||
|
colors: {
|
||||||
|
primary: 'rgb(10, 132, 255)',
|
||||||
|
background: "rgba(140, 140, 161, 1)",
|
||||||
|
card: 'rgb(18, 18, 18)',
|
||||||
|
text: 'rgb(229, 229, 231)',
|
||||||
|
border: 'rgb(39, 39, 41)',
|
||||||
|
notification: 'rgb(255, 69, 58)',
|
||||||
|
},
|
||||||
|
};
|
After Width: | Height: | Size: 209 B |
After Width: | Height: | Size: 315 B |
After Width: | Height: | Size: 301 B |
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
export enum ActionType {
|
||||||
|
SET_THEME = 'SET_THEME',
|
||||||
|
}
|
||||||
|
|
||||||
|
type actionFetch = {
|
||||||
|
type: ActionType.SET_THEME;
|
||||||
|
payload: String;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Action = actionFetch;
|
||||||
|
|
||||||
|
export const setTheme = (theme) => {
|
||||||
|
return {
|
||||||
|
type: ActionType.SET_THEME,
|
||||||
|
payload: theme,
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
import {CustomJoke} from "../../model/CustomJoke";
|
||||||
|
import {SampleJoke} from "../../model/SampleJoke";
|
||||||
|
|
||||||
|
export enum ActionType {
|
||||||
|
ADD_FAVORITE = 'ADD_CUSTOM_FAVORITE',
|
||||||
|
REMOVE_FAVORITE = "REMOVE_CUSTOM_FAVORITE"
|
||||||
|
}
|
||||||
|
|
||||||
|
type actionAddFetch = {
|
||||||
|
type: ActionType.ADD_FAVORITE;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
type actionRemoveFetch = {
|
||||||
|
type: ActionType.REMOVE_FAVORITE;
|
||||||
|
payload: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Action = actionAddFetch | actionRemoveFetch;
|
||||||
|
|
||||||
|
export const addFavorite = (joke: CustomJoke | SampleJoke) => ({
|
||||||
|
type: ActionType.ADD_FAVORITE,
|
||||||
|
payload: joke,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const removeFavorite = (joke: CustomJoke | SampleJoke) => ({
|
||||||
|
type: ActionType.REMOVE_FAVORITE,
|
||||||
|
payload: joke,
|
||||||
|
});
|
@ -0,0 +1,21 @@
|
|||||||
|
import {Action, ActionType} from "../actions/DarkModeAction";
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
theme: String
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
theme: 'dark'
|
||||||
|
}
|
||||||
|
|
||||||
|
const themeReducer = (state: State = initialState, action: Action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case ActionType.SET_THEME:
|
||||||
|
// @ts-ignore
|
||||||
|
return {...state, theme: action.payload};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default themeReducer;
|
@ -0,0 +1,26 @@
|
|||||||
|
import {Action, ActionType} from "../actions/FavoriteAction";
|
||||||
|
import {CustomJoke} from "../../model/CustomJoke";
|
||||||
|
import {SampleJoke} from "../../model/SampleJoke";
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
joke: CustomJoke | SampleJoke
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
joke: new CustomJoke('', '', '', '', '')
|
||||||
|
}
|
||||||
|
|
||||||
|
const favoriteReducer = (state: State = initialState, action: Action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case ActionType.ADD_FAVORITE:
|
||||||
|
// @ts-ignore
|
||||||
|
return {...state, joke: action.payload};
|
||||||
|
case ActionType.REMOVE_FAVORITE:
|
||||||
|
// @ts-ignore
|
||||||
|
return {...state, joke: action.payload};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default favoriteReducer;
|
@ -0,0 +1,28 @@
|
|||||||
|
import { setDeleteJoke } from "../actions/CustomJoke";
|
||||||
|
|
||||||
|
export const deleteItem = (id: string) => {
|
||||||
|
return async dispatch => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`https://iut-weather-api.azurewebsites.net/jokes/${id}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
"Content-Type": 'application/json',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
dispatch(setDeleteJoke(id)); // Supprimer la blague dans le store Redux
|
||||||
|
console.log('Suppression de la blague réussie');
|
||||||
|
} else {
|
||||||
|
console.log('Erreur lors de la requête DELETE');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Erreur :', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteCustomJoke = (jokeId) => {
|
||||||
|
return deleteItem(jokeId)
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
// Fonction pour ajouter une blague aux favoris
|
||||||
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||||
|
import {SampleJoke} from "../../model/SampleJoke";
|
||||||
|
import {CustomJoke} from "../../model/CustomJoke";
|
||||||
|
|
||||||
|
const addFavorite = async (joke: SampleJoke | CustomJoke) => {
|
||||||
|
try {
|
||||||
|
let favorites: { sampleJokes: SampleJoke[], customJokes: CustomJoke[] } = await AsyncStorage.getItem('@favorites');
|
||||||
|
if (!favorites) {
|
||||||
|
favorites = { sampleJokes: [], customJokes: [] };
|
||||||
|
}
|
||||||
|
if (joke instanceof SampleJoke) {
|
||||||
|
favorites.sampleJokes.push(joke);
|
||||||
|
} else if (joke instanceof CustomJoke) {
|
||||||
|
favorites.customJokes.push(joke);
|
||||||
|
}
|
||||||
|
await AsyncStorage.setItem('@favorites', JSON.stringify(favorites));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error adding favorite:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeFavorite = async (jokeId: string | number) => {
|
||||||
|
try {
|
||||||
|
var favorites: { sampleJokes: SampleJoke[], customJokes: CustomJoke[] } = await AsyncStorage.getItem('@favorites');
|
||||||
|
if (!favorites) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
favorites.sampleJokes = favorites.sampleJokes.filter(joke => joke.id !== jokeId);
|
||||||
|
favorites.customJokes = favorites.customJokes.filter(joke => joke.id !== jokeId);
|
||||||
|
await AsyncStorage.setItem('@favorites', JSON.stringify(favorites));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error removing favorite:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getFavorites = async () => {
|
||||||
|
try {
|
||||||
|
const favoritesString = await AsyncStorage.getItem('@favorites');
|
||||||
|
if (favoritesString !== null) {
|
||||||
|
return JSON.parse(favoritesString);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting favorites:', error);
|
||||||
|
}
|
||||||
|
return { sampleJokes: [], customJokes: [] };
|
||||||
|
};
|
@ -0,0 +1,21 @@
|
|||||||
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||||
|
import {Theme} from "@react-navigation/native";
|
||||||
|
|
||||||
|
export const storeTheme = async (theme) => {
|
||||||
|
try {
|
||||||
|
const jsonValue = JSON.stringify(theme)
|
||||||
|
await AsyncStorage.setItem('@theme', jsonValue)
|
||||||
|
console.log("theme stored")
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getTheme = async () => {
|
||||||
|
try {
|
||||||
|
const jsonValue = await AsyncStorage.getItem('@theme')
|
||||||
|
return jsonValue != null ? JSON.parse(jsonValue) as Theme : null;
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
@ -1,21 +1,106 @@
|
|||||||
import { customJokeStub } from '../data/stub/CustomJokeStub';
|
|
||||||
import { sampleJokeStub } from '../data/stub/SampleJokeStub';
|
|
||||||
import JokeItems from "../components/JokeItems";
|
import JokeItems from "../components/JokeItems";
|
||||||
import '../types/extension';
|
import '../types/extension';
|
||||||
import {StyleSheet, View} from "react-native";
|
import {Image, SafeAreaView, StyleSheet, Text, TouchableOpacity, View} from "react-native";
|
||||||
import {purpleColor} from "../assets/Theme";
|
import {darksalmonColor, purpleColor, whiteColor} from "../assets/Theme";
|
||||||
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
|
import React, {useEffect, useState} from "react";
|
||||||
|
import {getCustomJokesList, getSampleJokesList} from "../redux/thunk/GetThunk";
|
||||||
|
|
||||||
|
export default function Favorites() {
|
||||||
|
// @ts-ignore
|
||||||
|
const sampleJokes = useSelector(state => state.sampleReducer.jokes);
|
||||||
|
// @ts-ignore
|
||||||
|
const customJokes = useSelector(state => state.customReducer.customJokes);
|
||||||
|
const [joke, setJoke] = useState([])
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const eye = require("../assets/eye_icon.png")
|
||||||
|
const hideEye = require("../assets/eye_off_icon.png")
|
||||||
|
|
||||||
|
const [showCustomJoke, setCustomJoke] = useState(false); // état local pour contrôler la visibilité de la description
|
||||||
|
const toggleDescription = () => {
|
||||||
|
setCustomJoke(!showCustomJoke);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(!showCustomJoke) {
|
||||||
|
const loadSamplesJokes = async () => {
|
||||||
|
// @ts-ignore
|
||||||
|
await dispatch(getSampleJokesList());
|
||||||
|
};
|
||||||
|
loadSamplesJokes();
|
||||||
|
setJoke(sampleJokes)
|
||||||
|
} else {
|
||||||
|
const loadCustomJokes = async () => {
|
||||||
|
// @ts-ignore
|
||||||
|
await dispatch(getCustomJokesList());
|
||||||
|
};
|
||||||
|
loadCustomJokes();
|
||||||
|
setJoke(customJokes)
|
||||||
|
}
|
||||||
|
}, [dispatch, customJokes, sampleJokes]);
|
||||||
|
|
||||||
export default function Catalogue() {
|
|
||||||
const allJokes = [...customJokeStub, ...sampleJokeStub];
|
|
||||||
return (
|
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}>
|
<View style={styles.container}>
|
||||||
<JokeItems jokes={allJokes}/>
|
<JokeItems jokes={joke}/>
|
||||||
</View>
|
</View>
|
||||||
|
</SafeAreaView>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
backgroundColor: purpleColor
|
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",
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -1,21 +1,99 @@
|
|||||||
import { customJokeStub } from '../data/stub/CustomJokeStub';
|
|
||||||
import { sampleJokeStub } from '../data/stub/SampleJokeStub';
|
|
||||||
import JokeItems from "../components/JokeItems";
|
|
||||||
import '../types/extension';
|
import '../types/extension';
|
||||||
import {StyleSheet, View} from "react-native";
|
import {Image, StyleSheet, Switch, Text, View} from "react-native";
|
||||||
import {purpleColor} from "../assets/Theme";
|
import {darksalmonColor, DefaultTheme, DarkTheme, greyColor, indigoColor, purpleColor, whiteColor} from "../assets/Theme";
|
||||||
|
import React, {useEffect, useState} from "react";
|
||||||
|
import {useTheme} from "@react-navigation/native";
|
||||||
|
import {storeTheme} from "../redux/thunk/ThemeThunk";
|
||||||
|
|
||||||
export default function Catalogue() {
|
export default function Catalogue() {
|
||||||
const allJokes = [...customJokeStub, ...sampleJokeStub];
|
const light_mode = require("../assets/light_mode.png")
|
||||||
|
const dark_mode = require("../assets/dark_mode.png")
|
||||||
|
const [isDark, setDark] = React.useState(false)
|
||||||
|
|
||||||
|
const toggleTheme = () => {
|
||||||
|
setDark(previousState => {
|
||||||
|
const theme = !previousState;
|
||||||
|
const newTheme = theme ? DarkTheme : DefaultTheme;
|
||||||
|
storeTheme(newTheme);
|
||||||
|
return theme;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = themeSettings();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<JokeItems jokes={allJokes}/>
|
<View style={styles.topText}>
|
||||||
|
<Text style={styles.title}>Réglages</Text>
|
||||||
|
<View style={styles.switchMode}>
|
||||||
|
<View style={styles.textContainer}>
|
||||||
|
<Image
|
||||||
|
source={isDark? dark_mode: light_mode}
|
||||||
|
style={styles.imageButton} />
|
||||||
|
<Text style={styles.darkModeText}>Dark Mode</Text>
|
||||||
|
</View>
|
||||||
|
<Switch
|
||||||
|
value={isDark}
|
||||||
|
onValueChange={toggleTheme}
|
||||||
|
style={styles.switchMode}
|
||||||
|
trackColor={{false: darksalmonColor, true: darksalmonColor}}
|
||||||
|
thumbColor={whiteColor} />
|
||||||
</View>
|
</View>
|
||||||
)
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function themeSettings() {
|
||||||
|
const theme = useTheme();
|
||||||
|
const colors = theme.colors;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
|
||||||
container: {
|
container: {
|
||||||
backgroundColor: purpleColor
|
paddingTop: 10,
|
||||||
|
paddingBottom: 10,
|
||||||
|
paddingLeft: 10,
|
||||||
|
paddingRight: 10,
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: colors.background,
|
||||||
|
flexDirection: 'column',
|
||||||
|
},
|
||||||
|
topText: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
padding: 10,
|
||||||
|
fontSize: 20,
|
||||||
|
color: whiteColor,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
},
|
||||||
|
imageButton : {
|
||||||
|
width: 30,
|
||||||
|
height:30,
|
||||||
|
alignSelf : "center",
|
||||||
|
tintColor: darksalmonColor,
|
||||||
|
},
|
||||||
|
switchMode: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
backgroundColor: indigoColor,
|
||||||
|
padding: 20,
|
||||||
|
margin: 10,
|
||||||
|
},
|
||||||
|
darkModeText: {
|
||||||
|
color: whiteColor,
|
||||||
|
fontSize: 20,
|
||||||
|
marginLeft: 10,
|
||||||
|
paddingTop: 5,
|
||||||
|
},
|
||||||
|
textContainer: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return styles;
|
||||||
|
}
|
Loading…
Reference in new issue