diff --git a/components/TypeTacticsInfoList.test.tsx b/components/TypeTacticsInfoList.test.tsx index 5ff2eae..0899a7d 100644 --- a/components/TypeTacticsInfoList.test.tsx +++ b/components/TypeTacticsInfoList.test.tsx @@ -3,10 +3,11 @@ import React from 'react'; import { render } from '@testing-library/react-native'; import TypeTacticsInfoList from './TypeTacticsInfoList'; +import { TypeName } from "../entities/TypeName"; describe('TypeTacticsInfoList component', () => { it('renders types correctly', () => { - const types = ['FIRE', 'WATER', 'GRASS']; + const types = [TypeName.FIRE, TypeName.WATER, TypeName.GRASS]; const { getByText } = render(); types.forEach(type => { diff --git a/entities/Move.ts b/entities/Move.ts index a824c21..bc81044 100644 --- a/entities/Move.ts +++ b/entities/Move.ts @@ -1,11 +1,14 @@ // entities/Move.ts -import { Type } from "./Type"; +import { Type } from "./Type"; +import { MoveCategoryName } from "./MoveCategoryName"; export interface Move { + id: string | null; name: string; - category: string; + category: MoveCategoryName; power: number; accuracy: number; type: Type; + schemaVersion: number; } diff --git a/entities/MoveCategoryName.ts b/entities/MoveCategoryName.ts new file mode 100644 index 0000000..ef12306 --- /dev/null +++ b/entities/MoveCategoryName.ts @@ -0,0 +1,5 @@ +export enum MoveCategoryName { + PHYSICAL = 'PHYSICAL', + SPECIAL = 'SPECIAL', + STATUS = 'STATUS', +} diff --git a/entities/Type.ts b/entities/Type.ts index 2ad552c..7e6642c 100644 --- a/entities/Type.ts +++ b/entities/Type.ts @@ -1,7 +1,9 @@ // entities/Type.ts +import { TypeName } from "./TypeName"; + export interface Type { - name: string; + name: TypeName; weakAgainst: string[]; effectiveAgainst: string[]; } diff --git a/entities/TypeName.ts b/entities/TypeName.ts new file mode 100644 index 0000000..ec0bdb1 --- /dev/null +++ b/entities/TypeName.ts @@ -0,0 +1,20 @@ +export enum TypeName { + NORMAL = 'NORMAL', + GRASS = 'GRASS', + ELECTRIC = 'ELECTRIC', + WATER = 'WATER', + FIRE = 'FIRE', + BUG = 'BUG', + GHOST = 'GHOST', + PSYCHIC = 'PSYCHIC', + STEEL = 'STEEL', + DARK = 'DARK', + FLYING = 'FLYING', + ICE = 'ICE', + POISON = 'POISON', + GROUND = 'GROUND', + ROCK = 'ROCK', + DRAGON = 'DRAGON', + FIGHTING = 'FIGHTING', + FAIRY = 'FAIRY', +} diff --git a/navigation/Navigation.tsx b/navigation/Navigation.tsx index 0c62f97..3f346cc 100644 --- a/navigation/Navigation.tsx +++ b/navigation/Navigation.tsx @@ -9,6 +9,7 @@ import HomeScreen from '../screens/HomeScreen'; import { createStackNavigator } from '@react-navigation/stack'; import { RootStackParamList, RootTabParamList } from "./navigationTypes"; import { Image, StyleSheet } from 'react-native'; +import MoveFormScreen from "../screens/moves/MoveFormScreen"; const Stack = createStackNavigator(); const Tab = createBottomTabNavigator(); @@ -22,6 +23,7 @@ const MoveStack = () => { component={MoveDetailScreen} options={({ route }) => ({ title: route.params.move.name })} /> + ); }; diff --git a/navigation/constants.ts b/navigation/constants.ts new file mode 100644 index 0000000..175d332 --- /dev/null +++ b/navigation/constants.ts @@ -0,0 +1,5 @@ +// navigation/constants.ts + +export const MOVE_DETAIL = 'MoveDetail'; +export const MOVE_FORM = 'MoveForm'; +export const MOVE_LIST = 'MoveList'; diff --git a/navigation/navigationTypes.ts b/navigation/navigationTypes.ts index 66f9358..e6b028c 100644 --- a/navigation/navigationTypes.ts +++ b/navigation/navigationTypes.ts @@ -5,6 +5,7 @@ import { Move } from "../entities/Move"; export type RootStackParamList = { MoveList: undefined; MoveDetail: { move: Move }; + MoveForm: { move?: Move }; }; export type RootTabParamList = { diff --git a/package.json b/package.json index 856919c..fc246db 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ }, "dependencies": { "@expo/webpack-config": "^18.0.1", + "@react-native-community/picker": "^1.8.1", "@react-navigation/bottom-tabs": "^6.5.7", "@react-navigation/native": "^6.1.6", "@react-navigation/stack": "^6.3.16", diff --git a/redux/actions/moveActions.ts b/redux/actions/moveActions.ts index 12cf0ce..247098c 100644 --- a/redux/actions/moveActions.ts +++ b/redux/actions/moveActions.ts @@ -4,6 +4,7 @@ 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 { @@ -12,6 +13,25 @@ export const setMoves = (moves: Move[]) => { }; } +export const createMove = (move: Move) => { + return async (dispatch: Dispatch) => { + try { + const response = await fetch(`${API_BASE_URL}/move`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(move), + }); + const data = await response.json(); + dispatch(setMoves(data)); + } + catch (error) { + console.error(error); + } + } +} + export const getMoves = () => { return async (dispatch: Dispatch) => { try { @@ -24,3 +44,39 @@ export const getMoves = () => { } } } + +export const updateMove = (id: string, move: Move) => { + return async (dispatch: Dispatch, getState: () => RootState) => { + try { + const response = await fetch(`${API_BASE_URL}/move/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(move), + }); + const updatedMove = await response.json(); + const moves = getState().move.moves.map((m: Move) => m.id === id ? updatedMove : m); + dispatch(setMoves(moves)); + } + catch (error) { + console.error(error); + } + } +} + +export const deleteMove = (id: string) => { + return async (dispatch: Dispatch, getState: () => RootState) => { + try { + await fetch(`${API_BASE_URL}/move/${id}`, { + method: 'DELETE', + }); + const moves = getState().move.moves.filter((m: Move) => m.id !== id); + dispatch(setMoves(moves)); + } + catch (error) { + console.error(error); + } + } +} + diff --git a/redux/store.ts b/redux/store.ts index 23c33cc..78aff04 100644 --- a/redux/store.ts +++ b/redux/store.ts @@ -1,10 +1,14 @@ // redux/store.ts -import { configureStore } from '@reduxjs/toolkit' -import moveReducer from './reducers/moveReducer'; +import { configureStore } from '@reduxjs/toolkit' +import moveReducer, { MoveState } from './reducers/moveReducer'; export type AppDispatch = typeof store.dispatch; +export type RootState = { + move: MoveState; +}; + const store = configureStore({ reducer: { move: moveReducer diff --git a/screens/moves/MoveDetailScreen.tsx b/screens/moves/MoveDetailScreen.tsx index d9cfc39..bb43015 100644 --- a/screens/moves/MoveDetailScreen.tsx +++ b/screens/moves/MoveDetailScreen.tsx @@ -1,30 +1,49 @@ // screens/moves/MoveDetailScreen.tsx -import React from 'react'; -import { ScrollView, StyleSheet, Text, View } from 'react-native'; -import { RouteProp } from '@react-navigation/native'; -import { RootStackParamList } from "../../navigation/navigationTypes"; -import TypeTacticsInfoList from "../../components/TypeTacticsInfoList" +import React, { useEffect } from 'react'; +import { Button, ScrollView, StyleSheet, Text, View } from 'react-native'; +import { RouteProp } from '@react-navigation/native'; +import { RootStackParamList } from "../../navigation/navigationTypes"; +import TypeTacticsInfoList from "../../components/TypeTacticsInfoList" +import { StackNavigationProp } from "@react-navigation/stack"; +import { MOVE_DETAIL, MOVE_FORM } from '../../navigation/constants'; +import { useSelector } from "react-redux"; +import { RootState } from "../../redux/store"; +import { Move } from "../../entities/Move"; -type MoveDetailScreenRouteProp = RouteProp; + +type MoveDetailScreenNavigationProp = StackNavigationProp; +type MoveDetailScreenRouteProp = RouteProp; type Props = { + navigation: MoveDetailScreenNavigationProp; route: MoveDetailScreenRouteProp; }; -const MoveDetailScreen = ({ route }: Props) => { - const { move } = route.params; +const MoveDetailScreen = ({ navigation, route }: Props) => { + const move = + useSelector( + (state: RootState) => state.move.moves.find( + (m: Move) => m.id === route.params.move.id + ) + ); + + + useEffect(() => { + navigation.setOptions({ title: move?.name }); + }, [move]); return ( - Name: {move.name} - Category: {move.category} - Power: {move.power} - Accuracy: {move.accuracy} - Type: {move.type.name} +