From 57a846972ca0361b3eec3156885f5afa028406ec Mon Sep 17 00:00:00 2001 From: anperederi Date: Thu, 28 Mar 2024 20:56:13 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20first=20part=20of=20theme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/Theme.ts | 29 ++++++- src/assets/bin.png | Bin 0 -> 209 bytes src/assets/dark_mode.png | Bin 0 -> 315 bytes src/assets/light_mode.png | Bin 0 -> 301 bytes src/components/JokeDetail.tsx | 41 +++++++--- src/navigation/NavigationBar.tsx | 21 +++++- src/package-lock.json | 31 ++++++++ src/package.json | 1 + src/redux/actions/CustomJoke.ts | 17 ++++- src/redux/actions/DarkModeAction.ts | 18 +++++ src/redux/actions/FavoriteAction.ts | 28 +++++++ src/redux/reducers/CustomReducer.ts | 13 ++-- src/redux/reducers/DarkModeReducer.ts | 21 ++++++ src/redux/reducers/FavoriteReducer.ts | 26 +++++++ src/redux/reducers/SampleReducer.ts | 4 +- src/redux/store.ts | 7 +- src/redux/thunk/DeleteThunk.ts | 28 +++++++ src/redux/thunk/FavoriteThunk.ts | 47 ++++++++++++ src/redux/thunk/GetByThunk.ts | 8 +- src/redux/thunk/GetThunk.ts | 2 +- src/redux/thunk/PostThunk.ts | 3 - src/redux/thunk/ThemeThunk.ts | 21 ++++++ src/screens/AddScreen.tsx | 5 +- src/screens/Catalogue.tsx | 41 +++++----- src/screens/Favorites.tsx | 105 +++++++++++++++++++++++--- src/screens/HomeScreen.tsx | 2 - src/screens/JokeDetailsScreen.tsx | 22 +++--- src/screens/Settings.tsx | 104 +++++++++++++++++++++---- src/yarn.lock | 21 +++++- 29 files changed, 579 insertions(+), 87 deletions(-) create mode 100644 src/assets/bin.png create mode 100644 src/assets/dark_mode.png create mode 100644 src/assets/light_mode.png create mode 100644 src/redux/actions/DarkModeAction.ts create mode 100644 src/redux/actions/FavoriteAction.ts create mode 100644 src/redux/reducers/DarkModeReducer.ts create mode 100644 src/redux/reducers/FavoriteReducer.ts create mode 100644 src/redux/thunk/DeleteThunk.ts create mode 100644 src/redux/thunk/FavoriteThunk.ts create mode 100644 src/redux/thunk/ThemeThunk.ts diff --git a/src/assets/Theme.ts b/src/assets/Theme.ts index e1d6e48..dc07d73 100644 --- a/src/assets/Theme.ts +++ b/src/assets/Theme.ts @@ -1,5 +1,32 @@ +import {Theme} from "@react-navigation/native"; + export const indigoColor = "rgba(14, 14, 44, 1)"; export const purpleColor = "rgba(74, 74, 104, 1)"; export const darksalmonColor = "rgba(233, 150, 122, 1)"; export const greyColor = "rgba(140, 140, 161, 1)"; -export const whiteColor = "rgba(239, 239, 253, 1)"; \ No newline at end of file +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)', + }, +}; \ No newline at end of file diff --git a/src/assets/bin.png b/src/assets/bin.png new file mode 100644 index 0000000000000000000000000000000000000000..2d460e3c329693f1016de47e4a4752ec23bbdca1 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|x;ERwfMMBwm)#- zz=Mu;?BRioMtkP5cssP2GhJ=Y5OK&U^jVZHaH@SDE5qM#6G^qOb4fsFF?hQAxvXPx#^+`lQR7gwJRf`J3Kn&}?%=u;NmrcJ+FL04w>GgWDfg6m$9!Z;|-697c%fa~a z7X+(_;Jnl;nobusdT~>rRP$QyJ+spG2v9M=?eQo#?pg4t)prF!rKp&l>_UJFZ$)Pf zMuI7MybcI%pY2Xyr64gSOWR;g?p3NypOVQE&|EKFnJ!q!_xl+F$fD;0GU|CiFhJ1w zmz79su7lut(fDKuGBN;^!^ZUiP*&dr#1i~$W|Id;owVKN-HqxnTeR N002ovPDHLkV1hW*g@XV9 literal 0 HcmV?d00001 diff --git a/src/assets/light_mode.png b/src/assets/light_mode.png new file mode 100644 index 0000000000000000000000000000000000000000..b20bc418631545e10d566e2af398f671bfa17bba GIT binary patch literal 301 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|o_o4DhIn{i zo%)*hkO5E2-IEPqs4!nddHW~jKOCXTp}x0&OOxkzOksEwZ3>}R;9ocol^HN68Vb#Ke( zF>Wq#INc?sn{vdJh3Q@Iro&o|tjn_)a^24uGT*-wsCr_Hgi*6v!0+6Zm%qnN)zULm zJa=EnMI_B+h26`#l_ncZ6gG5a>dv-W>E)1qIVa1!f1ZEI66v#LDdtbR-o0AkVS8_4 vkZzgfn`QFXC#F``_t@WBC!2EeZoa(GF*nJhk(); + const navigation = useNavigation(); const toggleDescription = () => { setShowDescription(!showDescription); @@ -20,10 +33,11 @@ export default function JokeDetail(props: JokeItemProps) { setShowFavorite(!showFavorite); }; - const eye = require("../assets/eye_icon.png") - const hideEye = require("../assets/eye_off_icon.png") - const heart = require("../assets/favorite_icon.png") - const heartPlain = require("../assets/plain_favorite_icon.png") + const deleteCustomJokes = async () => { + await dispatch(deleteCustomJoke(props.joke.id)); + await dispatch(getCustomJokesList()); + navigation.goBack(); + }; return( @@ -33,6 +47,15 @@ export default function JokeDetail(props: JokeItemProps) { Résumé de la blague + {isCustom && ( + + + + ) + } (DefaultTheme); + + useEffect(() => { + const fetchTheme = async () => { + const theme = await getTheme(); + setTheme(theme); + }; + + fetchTheme(); + }); + + if (themes == null) { + return null; + } + return ( - + =0.60 <1.0" + } + }, "node_modules/@react-native-community/cli": { "version": "12.3.0", "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-12.3.0.tgz", @@ -8667,6 +8679,14 @@ "node": ">=8" } }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -9860,6 +9880,17 @@ "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", "integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA==" }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", diff --git a/src/package.json b/src/package.json index 747d634..40c61b9 100644 --- a/src/package.json +++ b/src/package.json @@ -10,6 +10,7 @@ "web": "expo start --web" }, "dependencies": { + "@react-native-async-storage/async-storage": "^1.23.1", "@react-navigation/bottom-tabs": "^6.5.11", "@react-navigation/native": "^6.1.10", "@react-navigation/stack": "^6.3.21", diff --git a/src/redux/actions/CustomJoke.ts b/src/redux/actions/CustomJoke.ts index 9aa9cd8..126e3aa 100644 --- a/src/redux/actions/CustomJoke.ts +++ b/src/redux/actions/CustomJoke.ts @@ -4,7 +4,8 @@ import {SampleJoke} from "../../model/SampleJoke"; export enum ActionType { FETCH_CUSTOM_JOKES = 'FETCH_CUSTOM_JOKES', POST_CUSTOM_JOKE = "POST_CUSTOM_JOKE", - FETCH_JOKES_BY_ID = "FETCH_JOKES_BY_ID" + FETCH_JOKES_BY_ID = "FETCH_JOKES_BY_ID", + DELETE_CUSTOM_JOKE = "DELETE_CUSTOM_JOKE" } type actionPostFetch = { @@ -19,7 +20,12 @@ type actionGetByFetch = { type: ActionType.FETCH_JOKES_BY_ID; payload: CustomJoke; } -export type Action = actionPostFetch | actionGetFetch | actionGetByFetch; +type actionDeleteFetch = { + type: ActionType.DELETE_CUSTOM_JOKE; + payload: string; +} + +export type Action = actionPostFetch | actionGetFetch | actionGetByFetch | actionDeleteFetch; export const setPostJoke = (customJoke: CustomJoke) => { return { @@ -27,7 +33,6 @@ export const setPostJoke = (customJoke: CustomJoke) => { payload: customJoke } } - export const setCustomJokesList = (customJokesList: CustomJoke[]) => { return { type: ActionType.FETCH_CUSTOM_JOKES, @@ -39,4 +44,10 @@ export const setCustomJokeById = (customJoke: CustomJoke) => { type: ActionType.FETCH_JOKES_BY_ID, payload: customJoke, }; +} +export const setDeleteJoke = (jokeId: string) => { + return { + type: ActionType.DELETE_CUSTOM_JOKE, + payload: jokeId + } } \ No newline at end of file diff --git a/src/redux/actions/DarkModeAction.ts b/src/redux/actions/DarkModeAction.ts new file mode 100644 index 0000000..e562e0c --- /dev/null +++ b/src/redux/actions/DarkModeAction.ts @@ -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, + }; +} \ No newline at end of file diff --git a/src/redux/actions/FavoriteAction.ts b/src/redux/actions/FavoriteAction.ts new file mode 100644 index 0000000..34ab52f --- /dev/null +++ b/src/redux/actions/FavoriteAction.ts @@ -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, +}); \ No newline at end of file diff --git a/src/redux/reducers/CustomReducer.ts b/src/redux/reducers/CustomReducer.ts index 9811438..219edf1 100644 --- a/src/redux/reducers/CustomReducer.ts +++ b/src/redux/reducers/CustomReducer.ts @@ -1,29 +1,28 @@ 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; + customJoke?: CustomJoke; + jokeId: string; } const initialState = { customJokes: [], - customJoke: new CustomJoke('', '', '', '') + customJoke: null, + jokeId: '' } 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_CUSTOM_JOKES: - // @ts-ignore return {...state, customJokes: action.payload}; case ActionType.FETCH_JOKES_BY_ID: - // @ts-ignore return {...state, customJoke: action.payload}; + case ActionType.DELETE_CUSTOM_JOKE: + return {...state, jokeId: action.payload}; default: return state; } diff --git a/src/redux/reducers/DarkModeReducer.ts b/src/redux/reducers/DarkModeReducer.ts new file mode 100644 index 0000000..714509b --- /dev/null +++ b/src/redux/reducers/DarkModeReducer.ts @@ -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; \ No newline at end of file diff --git a/src/redux/reducers/FavoriteReducer.ts b/src/redux/reducers/FavoriteReducer.ts new file mode 100644 index 0000000..f0eabee --- /dev/null +++ b/src/redux/reducers/FavoriteReducer.ts @@ -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; diff --git a/src/redux/reducers/SampleReducer.ts b/src/redux/reducers/SampleReducer.ts index b63c6fe..14e3ea0 100644 --- a/src/redux/reducers/SampleReducer.ts +++ b/src/redux/reducers/SampleReducer.ts @@ -6,13 +6,13 @@ import {Category} from "../../model/Category"; interface State { jokes: SampleJoke[]; favoriteJokes: SampleJoke[]; - joke : SampleJoke; + joke? : SampleJoke; } const initialState = { jokes: [], favoriteJokes: [], - joke: new SampleJoke(1, "", "", "", ""), + joke:null, } const sampleReducer = (state: State = initialState, action: Action) => { diff --git a/src/redux/store.ts b/src/redux/store.ts index 4ce4fc3..d535741 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -2,12 +2,16 @@ import {configureStore} from '@reduxjs/toolkit' import sampleReducer from "./reducers/SampleReducer"; import categoryReducer from "./reducers/CategoryReducer"; import customReducer from "./reducers/CustomReducer"; +import themeReducer from "./reducers/DarkModeReducer" +import favoriteReducer from "./reducers/FavoriteReducer"; // Reference here all your application reducers const reducer = { sampleReducer: sampleReducer, categoryReducer: categoryReducer, customReducer: customReducer, + theme: themeReducer, + favorite: favoriteReducer } // @ts-ignore @@ -18,5 +22,6 @@ const store = configureStore({ serializableCheck: false }) },); - +export type AppState = ReturnType +export type AppDispatch = typeof store.dispatch export default store; \ No newline at end of file diff --git a/src/redux/thunk/DeleteThunk.ts b/src/redux/thunk/DeleteThunk.ts new file mode 100644 index 0000000..e7105fb --- /dev/null +++ b/src/redux/thunk/DeleteThunk.ts @@ -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) +} \ No newline at end of file diff --git a/src/redux/thunk/FavoriteThunk.ts b/src/redux/thunk/FavoriteThunk.ts new file mode 100644 index 0000000..b04f478 --- /dev/null +++ b/src/redux/thunk/FavoriteThunk.ts @@ -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: [] }; +}; diff --git a/src/redux/thunk/GetByThunk.ts b/src/redux/thunk/GetByThunk.ts index cb1d165..fb71b0a 100644 --- a/src/redux/thunk/GetByThunk.ts +++ b/src/redux/thunk/GetByThunk.ts @@ -6,19 +6,21 @@ import {setCustomJokeById} from "../actions/CustomJoke"; export const getItem = (uri:string, constructor : (json:any) => TItem, setItem: (item: TItem) => any) => { return async dispatch => { try { + console.log(";;;;;;;;;;;;;;", uri, ";;;;;;;;;;;;;;;;;;;") const promise = await fetch(uri); const Json = await promise.json(); const Item: TItem = constructor(Json); + console.log("===========", Item , "==================="); dispatch(setItem(Item)); } catch (error) { console.log('Error---------', error); } } } -export const getJokeById = (id) => { - return getItem('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 getJokeById = (id : number) => { + return getItem('https://iut-weather-api.azurewebsites.net/jokes/samples/' + id.toString() , (elt) => new SampleJoke(elt["id"], elt["type"], elt["setup"], elt["image"]), (item) => setJokeById(item)) } -export const getCustomJokeById = (id) => { +export const getCustomJokeById = (id: string) => { return getItem('https://iut-weather-api.azurewebsites.net/jokes/' + id , (elt) => new CustomJoke(elt["id"], elt["type"], elt["setup"], elt["image"]), (item) => setCustomJokeById(item)) } \ No newline at end of file diff --git a/src/redux/thunk/GetThunk.ts b/src/redux/thunk/GetThunk.ts index f5542c3..1f7fc30 100644 --- a/src/redux/thunk/GetThunk.ts +++ b/src/redux/thunk/GetThunk.ts @@ -13,7 +13,7 @@ export const getList = (uri:string, constructor : (json:any) => TList, se const List: TList[] = listJson.map(elt => constructor(elt)); dispatch(setList(List)); } catch (error) { - console.log('Error---------', error); + console.log(`Error In getList ${uri} ---------`, error); } } } diff --git a/src/redux/thunk/PostThunk.ts b/src/redux/thunk/PostThunk.ts index 8aa3838..effdf8d 100644 --- a/src/redux/thunk/PostThunk.ts +++ b/src/redux/thunk/PostThunk.ts @@ -1,7 +1,4 @@ import {setPostJoke} from "../actions/CustomJoke"; -import {SampleJoke} from "../../model/SampleJoke"; -import {setJokesList} from "../actions/SampleAction"; -import {getList} from "./GetThunk"; export const setItem = ( uri: string, diff --git a/src/redux/thunk/ThemeThunk.ts b/src/redux/thunk/ThemeThunk.ts new file mode 100644 index 0000000..70e0aab --- /dev/null +++ b/src/redux/thunk/ThemeThunk.ts @@ -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); + } +} \ No newline at end of file diff --git a/src/screens/AddScreen.tsx b/src/screens/AddScreen.tsx index 5488cab..381ab72 100644 --- a/src/screens/AddScreen.tsx +++ b/src/screens/AddScreen.tsx @@ -5,7 +5,7 @@ import '../types/extension'; import {useDispatch, useSelector} from "react-redux"; 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 {getCustomJokesList, getSampleJokesList} from "../redux/thunk/GetThunk"; import React, {useEffect} from "react"; import {postCustomJoke} from "../redux/thunk/PostThunk"; @@ -25,6 +25,9 @@ export default function AddScreen() { const handleCreate = () => { // @ts-ignore dispatch(postCustomJoke(joke, downgrade, category)); + // @ts-ignore + dispatch(getCustomJokesList()); + clearFields(); }; diff --git a/src/screens/Catalogue.tsx b/src/screens/Catalogue.tsx index 92ca324..c436f87 100644 --- a/src/screens/Catalogue.tsx +++ b/src/screens/Catalogue.tsx @@ -5,35 +5,40 @@ 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"; +const eye = require("../assets/eye_icon.png") +const hideEye = require("../assets/eye_off_icon.png") export default function Catalogue() { // @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") - useEffect(() => { - const loadSamplesJokes = async () => { - // @ts-ignore - await dispatch(getSampleJokesList()); - }; - 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 [showCustomJoke, setCustomJoke] = useState(false); const toggleDescription = () => { setCustomJoke(!showCustomJoke); - loadCustomJokes(); }; + 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]); + return ( @@ -48,7 +53,7 @@ export default function Catalogue() { - + ) diff --git a/src/screens/Favorites.tsx b/src/screens/Favorites.tsx index 7ac3ffc..9e10f34 100644 --- a/src/screens/Favorites.tsx +++ b/src/screens/Favorites.tsx @@ -1,21 +1,106 @@ -import { customJokeStub } from '../data/stub/CustomJokeStub'; -import { sampleJokeStub } from '../data/stub/SampleJokeStub'; 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 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 ( - - - + + + Afficher les exemples + + + + + + + + + + ) }; const styles = StyleSheet.create({ 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", } }); \ No newline at end of file diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx index 03f6c87..6b15f7f 100644 --- a/src/screens/HomeScreen.tsx +++ b/src/screens/HomeScreen.tsx @@ -6,8 +6,6 @@ import Categs from "../components/Categs"; import {useDispatch, useSelector} from "react-redux"; import {useEffect} from "react"; 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 diff --git a/src/screens/JokeDetailsScreen.tsx b/src/screens/JokeDetailsScreen.tsx index 830d884..524e556 100644 --- a/src/screens/JokeDetailsScreen.tsx +++ b/src/screens/JokeDetailsScreen.tsx @@ -5,35 +5,37 @@ import {useDispatch, useSelector} from "react-redux"; import React, {useEffect, useState} from "react"; import {getCustomJokeById, getJokeById} from "../redux/thunk/GetByThunk"; import JokeDetail from "../components/JokeDetail"; +import {AppDispatch, AppState} from "../redux/store"; +import {CustomJoke} from "../model/CustomJoke"; +import {SampleJoke} from "../model/SampleJoke"; export default function JokeDetailsScreen({route}) { const idJokeDetail = route.params.idJoke; - // @ts-ignore - const joke = useSelector(state => state.sampleReducer.jokes); - // @ts-ignore - const customJoke = useSelector(state => state.customReducer.customJoke); - const [isCustomJoke, setCustomJoke] = useState(false); // état local pour contrôler la visibilité de la description - // @ts-ignore - const dispatch = useDispatch(); + const joke = useSelector(state => state.sampleReducer.joke); + const customJoke = useSelector(state => state.customReducer.customJoke); + const [isCustomJoke, setCustomJoke] = useState(false); + const dispatch = useDispatch(); useEffect(() => { - if(idJokeDetail instanceof Number) { + if(typeof idJokeDetail == 'number') { const loadJoke = async () => { - // @ts-ignore await dispatch(getJokeById(idJokeDetail)); }; loadJoke(); setCustomJoke(!isCustomJoke) } else { const loadCustomJoke = async () => { - // @ts-ignore await dispatch(getCustomJokeById(idJokeDetail)); }; loadCustomJoke(); } }, [dispatch]); + + if(!joke && !customJoke) return null; + return ( + {/*@ts-ignore}*/} ) diff --git a/src/screens/Settings.tsx b/src/screens/Settings.tsx index 7ac3ffc..578b1ba 100644 --- a/src/screens/Settings.tsx +++ b/src/screens/Settings.tsx @@ -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 {StyleSheet, View} from "react-native"; -import {purpleColor} from "../assets/Theme"; +import {Image, StyleSheet, Switch, Text, View} from "react-native"; +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() { - 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 ( - + + Réglages + + + + Dark Mode + + + + - ) + ); }; -const styles = StyleSheet.create({ - container: { - backgroundColor: purpleColor - } -}); \ No newline at end of file +export function themeSettings() { + const theme = useTheme(); + const colors = theme.colors; + + const styles = StyleSheet.create({ + + container: { + 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; +} \ No newline at end of file diff --git a/src/yarn.lock b/src/yarn.lock index 6d982ee..cdccc55 100644 --- a/src/yarn.lock +++ b/src/yarn.lock @@ -1707,6 +1707,13 @@ mkdirp "^1.0.4" rimraf "^3.0.2" +"@react-native-async-storage/async-storage@^1.23.1": + version "1.23.1" + resolved "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.23.1.tgz" + integrity sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA== + dependencies: + merge-options "^3.0.4" + "@react-native-community/cli-clean@12.3.0": version "12.3.0" resolved "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-12.3.0.tgz" @@ -3982,6 +3989,11 @@ is-path-inside@^3.0.2: resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" @@ -4430,6 +4442,13 @@ memory-cache@~0.2.0: resolved "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz" integrity sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA== +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" @@ -5368,7 +5387,7 @@ react-native-safe-area-context@^4.9.0, "react-native-safe-area-context@>= 3.0.0" react-freeze "^1.0.0" warn-once "^0.1.0" -react-native@*, react-native@>=0.69, react-native@0.73.2: +react-native@*, "react-native@^0.0.0-0 || >=0.60 <1.0", react-native@>=0.69, react-native@0.73.2: version "0.73.2" resolved "https://registry.npmjs.org/react-native/-/react-native-0.73.2.tgz" integrity sha512-7zj9tcUYpJUBdOdXY6cM8RcXYWkyql4kMyGZflW99E5EuFPoC7Ti+ZQSl7LP9ZPzGD0vMfslwyDW0I4tPWUCFw==