Tony Fages 1 year ago
parent f09a8fcc8f
commit 9bbb4d508b

@ -3,3 +3,5 @@
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# GitHub Copilot persisted chat sessions
/copilot/chatSessions

@ -1,5 +1,75 @@
import {DarkTheme, Theme, useTheme} from "@react-navigation/native";
import React, {useEffect, useState} from "react";
import DefaultTheme from "@react-navigation/native/src/theming/DefaultTheme";
import {useColorScheme} from "react-native";
export const indigo = "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)";
export const whiteColor = "rgba(239, 239, 253, 1)";
export const blackColor = "rgba(0, 0, 0, 1)";
export default function usePersonalTheme() {
useTheme()
const theme = React.useContext(ThemeContext);
const [isDark, setIsDark] = useState(false);
if (isDark) {
theme.dark = true;
theme.colors = MyDarkTheme.colors;
}
else {
theme.dark = false;
theme.colors = MyLightTheme.colors;
}
return theme;
}
//const isDark = false;
const MyDarkTheme: Theme = {
dark: true,
colors: {
primary: indigo,
background: purpleColor,
card: darksalmonColor,
text: whiteColor,
border: whiteColor,
notification: whiteColor,
},
};
const MyLightTheme: Theme = {
dark: false,
colors: {
primary: whiteColor,
background: greyColor,
card: '',
text: blackColor,
border: blackColor,
notification: blackColor,
},
};
const ThemeContext = React.createContext<Theme>(MyDarkTheme);

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

@ -1,9 +1,9 @@
import React from "react";
import {NavigationContainer} from "@react-navigation/native";
import React, {useContext, useEffect, useState} from "react";
import {DarkTheme, DefaultTheme, NavigationContainer, Theme, useTheme} from "@react-navigation/native";
import {createBottomTabNavigator} from "@react-navigation/bottom-tabs";
import {ListJokeScreen} from "../screens/ListJokeScreen";
import {Image, StyleSheet, View} from "react-native";
import {darksalmonColor, greyColor, indigo, purpleColor} from "../Theme";
import {Image, StyleSheet, useColorScheme, View} from "react-native";
import usePersonalTheme, {darksalmonColor, greyColor, indigo, purpleColor} from "../Theme";
import {AccueilScreen} from "../screens/AccueilScreen";
import {AddJokeScreen} from "../screens/AddJokeScreen";
import {SettingsScreen} from "../screens/SettingsScreen";
@ -14,24 +14,46 @@ const listIcon = require("../assets/list_icon.png");
const addIcon = require("../assets/add_icon.png");
const favIcon = require("../assets/favorite_icon.png");
const setIcon = require("../assets/settings_icon.png");
import store, {getTheme, storeTheme} from "../redux/store";
export function Navigation(){
const BottomTabNavigator = createBottomTabNavigator();
const [themes, setThemes] = useState<Theme | null>(null);
useEffect(() => {
const fetchTheme = async () => {
const theme = await getTheme();
setThemes(theme);
};
fetchTheme();
});
if (themes == null) {
return null;
}
console.log("ici le theme", themes);
return (
<NavigationContainer>
<BottomTabNavigator.Navigator initialRouteName="Home" screenOptions={{
<NavigationContainer theme={ themes.dark === false ? DefaultTheme : DarkTheme} >
<BottomTabNavigator.Navigator initialRouteName="Home" screenOptions={{
headerTitleStyle: {
fontSize: 24,
fontWeight: 'bold',
color: darksalmonColor,
color: themes.colors.text,
},
headerStyle: {
backgroundColor: indigo,
},
tabBarShowLabel: false,
tabBarStyle: styles.top,
}} >
}}>
<BottomTabNavigator.Screen name="Accueil" component={AccueilScreen}
options={{
tabBarIcon: ({focused}) => (
@ -108,3 +130,30 @@ const styles = StyleSheet.create({
});
const stylesDark = StyleSheet.create({
title: {
fontSize: 24,
color: 'darksalmon',
textAlign: 'center',
fontWeight: 'bold',
marginVertical: 20,
},
top: {
backgroundColor : indigo
},
addJoke: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: greyColor,
width: '70%',
height: '100%',
borderRadius: 4,
marginTop: 4,
},
});

@ -9,6 +9,7 @@
"version": "1.0.0",
"dependencies": {
"@expo/ngrok": "^2.5.0",
"@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",
@ -3883,6 +3884,17 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@react-native-async-storage/async-storage": {
"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"
},
"peerDependencies": {
"react-native": "^0.0.0-0 || >=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",
@ -9112,6 +9124,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",
@ -10329,6 +10349,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",

@ -10,6 +10,7 @@
},
"dependencies": {
"@expo/ngrok": "^2.5.0",
"@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",

@ -5,6 +5,7 @@ export enum CustomActionType {
POST_CUSTOM_JOKE = 'POST_CUSTOM_JOKE',
FETCH_CUSTOMS_JOKE = 'FETCH_CUSTOMS_JOKE',
FETCH_CUSTOMS_JOKE_BY_ID = 'FETCH_CUSTOMS_JOKE_BY_ID',
DELETE_CUSTOM_JOKE = 'DELETE_CUSTOM_JOKE',
}
export interface CustomAction {
@ -47,6 +48,13 @@ export const setCustomsJokeById = (completCustomJoke: CustomJoke): postCustomAct
}
export const setDeleteCustomJoke = (deleteCustomJoke: CustomJoke): postCustomAction => {
return {
type: CustomActionType.DELETE_CUSTOM_JOKE,
payload: deleteCustomJoke
}
}
export const postJoke = (type : string, setup : string, punchline : string) => {
@ -101,3 +109,21 @@ export const getJokesCustomsById = (id : number) => {
}
}
}
export const deleteJoke = (id : number) => {
return async dispatch => {
try {
const custom = await fetch('https://iut-weather-api.azurewebsites.net/jokes/' + id, {
method: 'DELETE',
headers: {
Accept: "application/json",
"Content-Type": "application/json",
}
});
console.log('Suppression');
dispatch(setDeleteCustomJoke({} as CustomJoke));
} catch (error) {
console.log('Error---------', error);
}
}
}

@ -7,6 +7,7 @@ interface state {
postJoke: CustomJoke;
customJokes: CustomJoke[];
completCustomJoke: CustomJoke;
deleteCustomJoke: CustomJoke;
}
// initial state for sampleJokes
@ -14,6 +15,7 @@ const initialState: state = {
postJoke: {} as CustomJoke,
customJokes: [],
completCustomJoke: {} as CustomJoke,
deleteCustomJoke: {} as CustomJoke,
}
// app reducer for sampleJokes
@ -35,6 +37,11 @@ export default appReducer = (state = initialState, action: Action) => {
...state,
completCustomJoke: action.payload,
}
case CustomActionType.DELETE_CUSTOM_JOKE:
return {
...state,
deleteCustomJoke: action.payload,
}
default:
return state;

@ -2,6 +2,8 @@ import { configureStore } from '@reduxjs/toolkit';
import categorieReducer from './reducers/categoryReducer';
import sampleReducer from './reducers/sampleJokeReducer';
import customReducer from "./reducers/customJokeReducer";
import AsyncStorage from '@react-native-async-storage/async-storage';
import {Theme} from "@react-navigation/native";
const reducer = {
categorieReducer: categorieReducer,
@ -20,4 +22,23 @@ const store = configureStore({
})
});
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);
}
}
export default store;

@ -1,4 +1,4 @@
import {View, Text, StyleSheet} from "react-native";
import {View, Text, StyleSheet, TouchableOpacity, Image} from "react-native";
import {indigo, purpleColor, whiteColor} from "../Theme";
import React, {useEffect} from "react";
import {CustomJoke} from "../model/CustomJoke";
@ -6,19 +6,20 @@ import {DetailJoke} from "../components/DetailJoke";
import {Joke} from "../model/Joke";
import {useDispatch, useSelector} from "react-redux";
import {getCompletJokes, setCompletJokes, setSample} from "../redux/actions/sampleAction";
import {validatePathConfig} from "@react-navigation/native";
import {getJokesCustomsById} from "../redux/actions/customAction";
//svjh
import {useIsFocused, useNavigation, validatePathConfig} from "@react-navigation/native";
import {deleteJoke, getJokesCustomsById} from "../redux/actions/customAction";
import {Navigation} from "../navigation/Navigation";
export default function JokeDetailScreen({route}) {
const navigation = useNavigation();
const isFocused = useIsFocused();
const dispatch = useDispatch();
const jokeId = route.params.joke;
const state = route.params.state;
console.log(state);
// Déterminer quelle donnée utiliser en fonction de l'état de `state`
const DataGen = state ? useSelector((state: any) => state.customReducer.completCustomJoke) : useSelector((state: any) => state.sampleReducer.completJoke);
// const DataGen = useSelector((state: any) => state.sampleReducer.completJoke);
const dispatch = useDispatch();
useEffect(() => {
const getDetails = async () => {
// @ts-ignore
@ -27,10 +28,19 @@ export default function JokeDetailScreen({route}) {
};
getDetails();
}, [dispatch]);
async function deleteJokes() {
// @ts-ignore
await dispatch(deleteJoke(jokeId));
navigation.goBack();
}
return (
<View style={styles.font}>
<DetailJoke item={DataGen}/>
{state ? <TouchableOpacity onPress={deleteJokes}>
<Image style={styles.img} source={require('../assets/delete-icon.png')} />
</TouchableOpacity> : null}
</View>
);
}
@ -48,5 +58,11 @@ const styles = StyleSheet.create({
textAlign: 'center',
fontWeight: 'bold',
marginVertical: 20,
},
img: {
width: 50,
height: 50,
margin: 20,
alignSelf: 'center'
}
});

@ -1,33 +1,52 @@
import {FlatList, Image, SafeAreaView, StyleSheet, Text, TouchableHighlight, TouchableOpacity, View} from "react-native";
import React, {useEffect, useState} from "react";
import React, {useContext, useEffect, useState} from "react";
import {JokeListItems} from "../components/ListeJokeComponent";
import {darksalmonColor, indigo, purpleColor, whiteColor} from "../Theme";
import {darksalmonColor, greyColor, indigo, purpleColor, whiteColor} from "../Theme";
import {CustomJoke} from "../model/CustomJoke";
import {useDispatch, useSelector} from 'react-redux';
import {getSampleJoke, setSample} from "../redux/actions/sampleAction";
import {getJokesCustoms} from "../redux/actions/customAction";
import {useIsFocused} from "@react-navigation/native";
export function ListJokeScreen({route, navigation}) {
const [isActivated2, setIsActivated2] = useState(false);
const isFocused = useIsFocused();
const [styles, setStyles] = useState(stylesLight);
function toggleActivation2() {
setIsActivated2(!isActivated2);
getCustoms();
}
const DataGen = useSelector((state: any) => state.sampleReducer.sampleJoke);
const DataCustomsJoke = useSelector((state : any) => state.customReducer.customJokes)
const dispatch = useDispatch();
useEffect(() => {
const getJokes = async () => {
// @ts-ignore
await dispatch(getSampleJoke());
};
getJokes();
}, [dispatch]);
const getCustoms = async () => {
// @ts-ignore
await dispatch(getJokesCustoms());
}
const getSamples = async () => {
// @ts-ignore
await dispatch(getSampleJoke());
}
useEffect(() => {
if (isFocused) {
if (isActivated2) {
getCustoms();
} else {
getSamples();
}
}
}, [isFocused, isActivated2]);
return (
<SafeAreaView style={styles.container}>
<View style={styles.header}>
@ -48,8 +67,7 @@ export function ListJokeScreen({route, navigation}) {
</SafeAreaView>
);
}
const styles = StyleSheet.create({
const stylesDark = StyleSheet.create({
title: {
fontSize: 24,
@ -103,4 +121,60 @@ const styles = StyleSheet.create({
},
});
const stylesLight = StyleSheet.create({
title: {
fontSize: 24,
color: darksalmonColor,
textAlign: 'center',
fontWeight: 'bold',
marginVertical: 20,
},
titleResume: {
fontSize: 15,
fontWeight: 'bold',
marginBottom: 20,
},
container: {
flex: 1,
backgroundColor: greyColor,
},
top: {
backgroundColor : indigo,
},
header: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
margin: 9,
},
headerText: {
fontSize: 18,
color: whiteColor,
textAlign: 'center',
fontWeight: 'bold',
},
img2: {
tintColor: whiteColor,
justifyContent: "center",
alignItems: "center",
},
button2:{
flexDirection: "row",
justifyContent: "center",
marginRight: 10,
borderRadius: 10,
alignItems: "center",
height: 30,
width: 70,
borderColor: darksalmonColor,
borderWidth: 1,
backgroundColor: darksalmonColor,
},
});

@ -1,33 +1,125 @@
import React from "react";
import React, {useContext, useEffect, useState} from "react";
import {
Appearance,
Button,
FlatList,
Image,
SafeAreaView,
ScrollView,
SectionListComponent,
StyleSheet, Switch, SwitchComponent,
Text, useColorScheme,
View
} from "react-native";
import usePersonalTheme, {
blackColor,
darksalmonColor,
greyColor,
indigo,
purpleColor,
whiteColor
} from "../Theme";
import {isEnabled} from "react-native/Libraries/Performance/Systrace";
import {DarkTheme, DefaultTheme, useTheme} from "@react-navigation/native";
import {storeTheme} from "../redux/store";
import {FlatList, Image, SafeAreaView, ScrollView, SectionListComponent, StyleSheet, Text, View} from "react-native";
import {indigo, purpleColor} from "../Theme";
export function SettingsScreen() {
const [isEnabled, setIsEnabled] = useState(false);
const toggleSwitch = () => {
setIsEnabled(previousState => {
const newIsEnabled = !previousState;
const newTheme = newIsEnabled ? DarkTheme : DefaultTheme;
console.log("newTheme", newTheme);
storeTheme(newTheme);
return newIsEnabled;
});
};
const styles = themeSettings();
return (
<View style={styles.font}>
<Text style={styles.text}>Settings Page</Text>
<Text style={styles.text}>In Work</Text>
</View>
<SafeAreaView style={styles.container}>
<Text style={styles.title}>Réglages</Text>
<View style={styles.settingsContainer}>
<View style={styles.settingRow}>
<View style={styles.settingRow}>
<Image style={styles.img} source={require('../assets/darkmode_icon.png')}/>
<Text style={styles.settingText}>Dark Mode</Text>
</View>
<Switch style={styles.switch}
trackColor={{ false: whiteColor, true: darksalmonColor }}
thumbColor={isEnabled ? whiteColor :darksalmonColor}
onValueChange={toggleSwitch}
value={isEnabled}
/>
</View>
</View>
</SafeAreaView>
);
}
};
export function themeSettings() {
const theme = useTheme();
const colors = theme.colors;
console.log("themeSettings", colors)
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.background,
},
header: {
padding: 16,
alignItems: 'center',
},
headerText: {
color: whiteColor,
fontSize: 18,
},
settingsContainer: {
backgroundColor: indigo,
margin: 16,
},
title: {
color: whiteColor,
fontSize: 20,
fontWeight: 'bold',
marginTop: 7,
marginLeft: 15,
marginBottom: 8,
},
settingRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingVertical: 12,
const styles = StyleSheet.create({
font: {
backgroundColor: indigo,
width: '100%',
height: '100%',
},
text: {
fontSize: 24,
color: 'darksalmon',
textAlign: 'center',
fontWeight: 'bold',
marginVertical: 20,
}
},
settingText: {
color: whiteColor,
marginLeft: 10,
},
img: {
marginLeft: 10,
width: 30,
height: 30,
tintColor: darksalmonColor,
},
switch: {
marginRight: 10,
}
});
return styles;
}
});
Loading…
Cancel
Save