🚨 Use constants in reducer

pull/11/head
Alexis Drai 2 years ago
parent d464e57af2
commit 232c7f9ed5

@ -1,17 +1,9 @@
// redux/actions/moveAction.ts // redux/actions/moveAction.ts
import { CREATE_MOVE, DELETE_MOVE, GET_MOVES, UPDATE_MOVE } from '../constants';
import { Move } from "../../entities/Move";
import { Dispatch } from "redux";
import { API_BASE_URL } from "../../config";
import { FETCH_MOVES } from '../constants';
import { Move } from "../../entities/Move";
import { Dispatch } from "redux";
import { API_BASE_URL } from "../../config";
import { RootState } from "../store";
export const setMoves = (moves: Move[]) => {
return {
type: FETCH_MOVES,
payload: moves,
};
}
export const createMove = (move: Move) => { export const createMove = (move: Move) => {
return async (dispatch: Dispatch) => { return async (dispatch: Dispatch) => {
@ -24,7 +16,7 @@ export const createMove = (move: Move) => {
body: JSON.stringify(move), body: JSON.stringify(move),
}); });
const data = await response.json(); const data = await response.json();
dispatch(setMoves(data)); dispatch({ type: CREATE_MOVE, payload: data });
} }
catch (error) { catch (error) {
console.error(error); console.error(error);
@ -37,7 +29,7 @@ export const getMoves = () => {
try { try {
const response = await fetch(`${API_BASE_URL}/move`); const response = await fetch(`${API_BASE_URL}/move`);
const data = await response.json(); const data = await response.json();
dispatch(setMoves(data)); dispatch({ type: GET_MOVES, payload: data });
} }
catch (error) { catch (error) {
console.error(error); console.error(error);
@ -46,7 +38,7 @@ export const getMoves = () => {
} }
export const updateMove = (id: string, move: Move) => { export const updateMove = (id: string, move: Move) => {
return async (dispatch: Dispatch, getState: () => RootState) => { return async (dispatch: Dispatch) => {
try { try {
const response = await fetch(`${API_BASE_URL}/move/${id}`, { const response = await fetch(`${API_BASE_URL}/move/${id}`, {
method: 'PUT', method: 'PUT',
@ -56,8 +48,7 @@ export const updateMove = (id: string, move: Move) => {
body: JSON.stringify(move), body: JSON.stringify(move),
}); });
const updatedMove = await response.json(); const updatedMove = await response.json();
const moves = getState().move.moves.map((m: Move) => m.id === id ? updatedMove : m); dispatch({ type: UPDATE_MOVE, payload: updatedMove });
dispatch(setMoves(moves));
} }
catch (error) { catch (error) {
console.error(error); console.error(error);
@ -66,17 +57,15 @@ export const updateMove = (id: string, move: Move) => {
} }
export const deleteMove = (id: string) => { export const deleteMove = (id: string) => {
return async (dispatch: Dispatch, getState: () => RootState) => { return async (dispatch: Dispatch) => {
try { try {
await fetch(`${API_BASE_URL}/move/${id}`, { await fetch(`${API_BASE_URL}/move/${id}`, {
method: 'DELETE', method: 'DELETE',
}); });
const moves = getState().move.moves.filter((m: Move) => m.id !== id); dispatch({ type: DELETE_MOVE, payload: id });
dispatch(setMoves(moves));
} }
catch (error) { catch (error) {
console.error(error); console.error(error);
} }
} }
} }

@ -1,3 +1,6 @@
// redux/constants.ts // redux/constants.ts
export const FETCH_MOVES = 'FETCH_MOVES'; export const GET_MOVES = 'FETCH_MOVES';
export const CREATE_MOVE = 'CREATE_MOVE';
export const UPDATE_MOVE = 'UPDATE_MOVE';
export const DELETE_MOVE = 'DELETE_MOVE';

@ -1,15 +1,14 @@
// redux/reducers/moveReducer.ts // redux/reducers/moveReducer.ts
import { FETCH_MOVES } from '../constants'; import { CREATE_MOVE, DELETE_MOVE, GET_MOVES, UPDATE_MOVE } from '../constants';
import { Move } from "../../entities/Move"; import { Move } from "../../entities/Move";
import { AnyAction } from "redux";
export type MoveState = { export type MoveState = {
moves: Move[]; moves: Move[];
}; };
type MoveAction = AnyAction & { type MoveAction = {
type: typeof FETCH_MOVES; type: string;
payload?: Move[]; payload?: Move | Move[] | string;
}; };
const initialState: MoveState = { const initialState: MoveState = {
@ -18,10 +17,25 @@ const initialState: MoveState = {
export default function moveReducer(state = initialState, action: MoveAction): MoveState { export default function moveReducer(state = initialState, action: MoveAction): MoveState {
switch (action.type) { switch (action.type) {
case FETCH_MOVES: case GET_MOVES:
return { ...state, moves: action.payload || [] }; return {
...state, moves: action.payload as Move[] || []
};
case CREATE_MOVE:
return {
...state, moves: [...state.moves, action.payload as Move]
};
case UPDATE_MOVE:
return {
...state,
moves: state.moves.map(move => move.id === (action.payload as Move).id ? action.payload as Move : move)
};
case DELETE_MOVE:
return {
...state,
moves: state.moves.filter(move => move.id !== action.payload)
};
default: default:
return state; return state;
} }
} }

@ -1,19 +1,19 @@
// screens/moves/MoveFormScreen.tsx // screens/moves/MoveFormScreen.tsx
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Button, StyleSheet, TextInput, View } from 'react-native'; import { Button, StyleSheet, Text, TextInput, View } from 'react-native';
import { StackNavigationProp } from '@react-navigation/stack'; import { StackNavigationProp } from '@react-navigation/stack';
import { RootStackParamList } from "../../navigation/navigationTypes"; import { RootStackParamList } from "../../navigation/navigationTypes";
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { createMove, updateMove } from '../../redux/actions/moveActions'; import { createMove, updateMove } from '../../redux/actions/moveActions';
import { AppDispatch } from "../../redux/store"; import { AppDispatch } from "../../redux/store";
import { Move } from "../../entities/Move"; import { Move } from "../../entities/Move";
import { RouteProp } from "@react-navigation/native"; import { RouteProp } from "@react-navigation/native";
import { MOVE_FORM } from "../../navigation/constants"; import { MOVE_FORM } from "../../navigation/constants";
import { Picker } from "@react-native-community/picker"; import { Picker } from "@react-native-community/picker";
import { ItemValue } from "@react-native-community/picker/typings/Picker"; import { ItemValue } from "@react-native-community/picker/typings/Picker";
import { MoveCategoryName } from "../../entities/MoveCategoryName"; import { MoveCategoryName } from "../../entities/MoveCategoryName";
import { TypeName } from "../../entities/TypeName"; import { TypeName } from "../../entities/TypeName";
type MoveFormScreenNavigationProp = StackNavigationProp<RootStackParamList, typeof MOVE_FORM>; type MoveFormScreenNavigationProp = StackNavigationProp<RootStackParamList, typeof MOVE_FORM>;
type MoveFormScreenRouteProp = RouteProp<RootStackParamList, typeof MOVE_FORM>; type MoveFormScreenRouteProp = RouteProp<RootStackParamList, typeof MOVE_FORM>;
@ -49,17 +49,18 @@ const MoveFormScreen = ({ navigation, route }: Props) => {
navigation.goBack(); navigation.goBack();
}; };
// TODO add labels and remove placeholders
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text>Name: </Text>
<TextInput <TextInput
value={move.name} value={move.name}
onChangeText={(text) => setMove({ ...move, name: text })} onChangeText={(text) => setMove({ ...move, name: text })}
placeholder="Name"
style={styles.input} style={styles.input}
/> />
<Text>Category: </Text>
<Picker <Picker
selectedValue={move.category} selectedValue={move.category}
style={styles.input}
onValueChange={(itemValue: ItemValue) => onValueChange={(itemValue: ItemValue) =>
setMove({ ...move, category: itemValue as MoveCategoryName }) setMove({ ...move, category: itemValue as MoveCategoryName })
}> }>
@ -67,22 +68,24 @@ const MoveFormScreen = ({ navigation, route }: Props) => {
<Picker.Item key={value} label={value} value={value}/> <Picker.Item key={value} label={value} value={value}/>
)} )}
</Picker> </Picker>
<Text>Power: </Text>
<TextInput <TextInput
value={move.power.toString()} value={move.power.toString()}
onChangeText={(text) => setMove({ ...move, power: Number(text) })} onChangeText={(text) => setMove({ ...move, power: Number(text) })}
placeholder="Power"
style={styles.input} style={styles.input}
keyboardType="numeric" keyboardType="numeric"
/> />
<Text>Accuracy: </Text>
<TextInput <TextInput
value={move.accuracy.toString()} value={move.accuracy.toString()}
onChangeText={(text) => setMove({ ...move, accuracy: Number(text) })} onChangeText={(text) => setMove({ ...move, accuracy: Number(text) })}
placeholder="Accuracy"
style={styles.input} style={styles.input}
keyboardType="numeric" keyboardType="numeric"
/> />
<Text>Type: </Text>
<Picker <Picker
selectedValue={move.type.name} selectedValue={move.type.name}
style={styles.input}
onValueChange={(itemValue: ItemValue) => onValueChange={(itemValue: ItemValue) =>
setMove({ ...move, type: { ...move.type, name: itemValue as TypeName } }) setMove({ ...move, type: { ...move.type, name: itemValue as TypeName } })
}> }>
@ -90,13 +93,12 @@ const MoveFormScreen = ({ navigation, route }: Props) => {
<Picker.Item key={value} label={value} value={value}/> <Picker.Item key={value} label={value} value={value}/>
)} )}
</Picker> </Picker>
{/*TODO add weakAgainst and effectiveAgainst columns... Two pickers for that, and the ability to keep adding types in each column.. but user can't put the same type in each column or twice in a column*/} {/*TODO add type.weakAgainst and type.effectiveAgainst columns... Two pickers for that, and the ability to keep adding types in each column.. but user can't put the same type in each column or twice in a column*/}
<Button title="Save" onPress={handleSave}/> <Button title="Save" onPress={handleSave}/>
</View> </View>
); );
}; };
// TODO improve styles a bit
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,

Loading…
Cancel
Save