parent
f1a4952a2a
commit
0cccc65a3e
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,13 +1,15 @@
|
||||
{
|
||||
"ExpandedNodes": [
|
||||
"",
|
||||
"\\assets",
|
||||
"\\components",
|
||||
"\\model",
|
||||
"\\navigation",
|
||||
"\\pages",
|
||||
"\\redux"
|
||||
"\\redux",
|
||||
"\\redux\\actions",
|
||||
"\\redux\\reducers",
|
||||
"\\redux\\thunks"
|
||||
],
|
||||
"SelectedNode": "\\components\\KanjiListCell.tsx",
|
||||
"SelectedNode": "\\components\\KanjiListSearchPanel.tsx",
|
||||
"PreviewInSolutionExplorer": false
|
||||
}
|
Binary file not shown.
@ -0,0 +1,78 @@
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Text, View, StyleSheet, TouchableOpacity, useColorScheme, Animated } from 'react-native';
|
||||
import { Check } from "react-native-feather";
|
||||
|
||||
interface gradeChipProps {
|
||||
grade: number;
|
||||
onSelect: (item: string, isSelected: Boolean) => void;
|
||||
}
|
||||
|
||||
const GradeChip = (props: gradeChipProps) => {
|
||||
|
||||
const [chipStyle, setChipStyle] = useState(style);
|
||||
|
||||
const [isSelected, setIsSelected] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setChipStyle(isSelected ? styleSELECTED : style);
|
||||
}, [isSelected]);
|
||||
|
||||
const select = () => {
|
||||
props.onSelect("Grade "+props.grade, isSelected);
|
||||
setIsSelected(!isSelected);
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity style={chipStyle.chip} onPress={() => { select() }}>
|
||||
<Text style={chipStyle.text}>Grade {props.grade}</Text>
|
||||
{isSelected && (<Check style={chipStyle.icon} />)}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
const style = StyleSheet.create({
|
||||
chip: {
|
||||
backgroundColor: "#FF5C5C",
|
||||
borderRadius: 10,
|
||||
margin: 5,
|
||||
justifyContent: "center",
|
||||
},
|
||||
icon: {
|
||||
color: "white",
|
||||
margin: 5
|
||||
},
|
||||
text: {
|
||||
color: "white",
|
||||
fontWeight: "bold",
|
||||
fontSize: "18em",
|
||||
padding: 5
|
||||
|
||||
},
|
||||
})
|
||||
|
||||
const styleSELECTED = StyleSheet.create({
|
||||
chip: {
|
||||
backgroundColor: "#FF5C5C",
|
||||
borderRadius: 10,
|
||||
margin: 5,
|
||||
justifyContent: "center",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
},
|
||||
icon: {
|
||||
color: "white",
|
||||
margin: 5
|
||||
},
|
||||
text: {
|
||||
color: "white",
|
||||
fontWeight: "bold",
|
||||
fontSize: "18em",
|
||||
padding: 5
|
||||
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
||||
export default GradeChip;
|
@ -0,0 +1,50 @@
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import React, { useState } from "react";
|
||||
import { FlatList, TextInput, StyleSheet, View } from "react-native";
|
||||
import GradeChip from './GradeChip';
|
||||
|
||||
interface kanjiListSeachPanelProps {
|
||||
onSelect: (item: string, isSelected: Boolean) => void;
|
||||
}
|
||||
|
||||
const KanjiListSearchPanel = (props: kanjiListSeachPanelProps) => {
|
||||
|
||||
const navigator = useNavigation();
|
||||
|
||||
return (
|
||||
<View style={panelStyle.container}>
|
||||
<TextInput style={panelStyle.input} />
|
||||
<FlatList
|
||||
data={[1, 2, 3, 4, 5, 6]}
|
||||
renderItem={(item) => <GradeChip grade={item.item} onSelect={props.onSelect} />}
|
||||
horizontal={true}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
|
||||
>
|
||||
</FlatList>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const panelStyle = StyleSheet.create({
|
||||
input: {
|
||||
height: 40,
|
||||
margin: 12,
|
||||
borderWidth: 1,
|
||||
padding: 10,
|
||||
width: 200,
|
||||
backgroundColor: "white",
|
||||
borderRadius: 20,
|
||||
borderColor: "black",
|
||||
width: "80%"
|
||||
},
|
||||
container: {
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
height: "20%"
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
export default KanjiListSearchPanel;
|
@ -0,0 +1,21 @@
|
||||
import { Kanji } from "./kanji"
|
||||
|
||||
export type KanjiListByGrade = {
|
||||
"Grade 1": Kanji[],
|
||||
"Grade 2": Kanji[],
|
||||
"Grade 3": Kanji[],
|
||||
"Grade 4": Kanji[],
|
||||
"Grade 5": Kanji[],
|
||||
"Grade 6": Kanji[],
|
||||
}[]
|
||||
|
||||
export const initKanjiListByGrade = (): KanjiListByGrade => {
|
||||
return {
|
||||
"Grade 1": [],
|
||||
"Grade 2": [],
|
||||
"Grade 3": [],
|
||||
"Grade 4": [],
|
||||
"Grade 5": [],
|
||||
"Grade 6": [],
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
import { Kanji } from "./kanji";
|
||||
|
||||
export class KanjiMapper {
|
||||
|
||||
static ApiJsonToKanji(json: any): Kanji {
|
||||
var radical: { character: string, position: string } = {
|
||||
character: json.radical.character,
|
||||
position: json.radical.position.icon
|
||||
};
|
||||
|
||||
var examples: { japanese: string, english: string }[] = [];
|
||||
|
||||
json.examples.forEach(
|
||||
(entry) => {
|
||||
examples.push({
|
||||
japanese: entry.japanese,
|
||||
english: entry.meaning.english
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
return new Kanji(json.kanji.character, json.kanji.meaning.english, json.kanji.video.poster,
|
||||
json.kanji.video.mp4, json.kanji.strokes.count, json.kanji.onyomi.katakana, json.kanji.kunyomi.hiragana,
|
||||
radical, examples);
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
static SerializedObjectToKanji(obj): Kanji | null {
|
||||
if (!obj) return null;
|
||||
return new Kanji(obj.character, obj.meaning, obj.image, obj.animation, obj.strokes, obj.onyomi, obj.kunyomi, obj.radical, obj.examples);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
export type kanjiSearchParams = {
|
||||
input: string
|
||||
grades: string[]
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
import { NavigationContainer, useNavigation } from "@react-navigation/native";
|
||||
import { createStackNavigator, StackNavigationOptions } from "@react-navigation/stack";
|
||||
import React, { useEffect } from "react";
|
||||
import { View, StyleSheet, Text } from "react-native";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { fetchKanjis } from "../redux/thunks/fetchKanjis";
|
||||
import TabBar from "./TabBar";
|
||||
|
||||
|
||||
const stackOptions: StackNavigationOptions = {
|
||||
headerShown: false,
|
||||
presentation: "modal"
|
||||
};
|
||||
|
||||
export const InitStack = () => {
|
||||
|
||||
const Stack = createStackNavigator();
|
||||
|
||||
return (
|
||||
<NavigationContainer>
|
||||
|
||||
<Stack.Navigator initialRouteName="Startup"
|
||||
screenOptions={stackOptions}
|
||||
>
|
||||
<Stack.Screen name="Startup" component={Startup} />
|
||||
<Stack.Screen name="Main"
|
||||
component={TabBar}
|
||||
options={{ animationEnabled: false }} />
|
||||
|
||||
|
||||
</Stack.Navigator>
|
||||
</NavigationContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Startup() {
|
||||
|
||||
const navigator = useNavigation();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const init = async () => {
|
||||
|
||||
await dispatch(await fetchKanjis());
|
||||
//await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
navigator.navigate("Main");
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
init()
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={splashscreenStyle.container}>
|
||||
<Text style={splashscreenStyle.title}>LEARNIHON</Text>
|
||||
</View>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
const splashscreenStyle = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
position: "absolute",
|
||||
backgroundColor: '#FF5C5C',
|
||||
},
|
||||
title: {
|
||||
color: 'white',
|
||||
textAlign: 'center',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 50,
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
import { Kanji } from '../../model/kanji';
|
||||
import { FETCH_KANJIS } from '../constants';
|
||||
|
||||
export const fetchKanjis = (kanjis: Kanji[]) => {
|
||||
return {
|
||||
type: FETCH_KANJIS,
|
||||
payload: kanjis,
|
||||
};
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
import { Kanji } from '../../model/kanji';
|
||||
import { SET_KANJIS } from '../constants';
|
||||
import { KanjiListByGrade } from '../../model/kanjiListByGrades';
|
||||
|
||||
export const setKanjis = (kanjis: kanjiListByGrade) => {
|
||||
return {
|
||||
type: SET_KANJIS,
|
||||
payload: kanjis,
|
||||
};
|
||||
}
|
@ -1,2 +1,2 @@
|
||||
export const FETCH_KANJIS = 'FETCH_KANJIS';
|
||||
export const SET_SELECTED_KANJI = 'SET_SELECTED_KANJI';
|
||||
export const SET_SELECTED_KANJI = 'SET_SELECTED_KANJI';
|
||||
export const SET_KANJIS = 'SET_KANJIS';
|
@ -0,0 +1,40 @@
|
||||
import { initKanjiListByGrade, KanjiListByGrade } from '../../model/kanjiListByGrades';
|
||||
import { KanjiMapper } from '../../model/kanjiMapper';
|
||||
import { setKanjis } from '../actions/setKanjis';
|
||||
|
||||
// @ts-ignore
|
||||
export const fetchKanjis = async () => {
|
||||
|
||||
const kanjis: KanjiListByGrade = initKanjiListByGrade();
|
||||
|
||||
const options = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-RapidAPI-Key': '19516a9900mshce10de76f99976bp10f192jsn8c8d82222baa',
|
||||
'X-RapidAPI-Host': 'kanjialive-api.p.rapidapi.com'
|
||||
}
|
||||
};
|
||||
|
||||
const fetchData = async (grade: string) => {
|
||||
return fetch(`https://kanjialive-api.p.rapidapi.com/api/public/search/advanced/?grade=${grade}`, options)
|
||||
}
|
||||
return async dispatch => {
|
||||
const fetchAll = async () => {
|
||||
for (let i = 1; i <= 6; i++) {
|
||||
await fetchData(i.toString()).then(async (response) => {
|
||||
const data = await response.json();
|
||||
data.forEach(async (it: object) => {
|
||||
await fetch(`https://kanjialive-api.p.rapidapi.com/api/public/kanji/${it.kanji.character}`, options)
|
||||
.then(async detail => {
|
||||
const detail_data = await detail.json();
|
||||
kanjis['Grade ' + i].push(KanjiMapper.ApiJsonToKanji(detail_data));
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
return fetchAll().then(_ => dispatch(setKanjis(kanjis)))
|
||||
.catch((err) => console.log("ERR : " + err));
|
||||
|
||||
};
|
||||
}
|
Loading…
Reference in new issue