Commit a12bc2cf authored by Soo Hyun Kim's avatar Soo Hyun Kim
Browse files

0721 notification 위치 수정중

parent 2178e112
......@@ -5,8 +5,8 @@ import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons';
import Monthly from './Monthly';
import Analy from './Analy';
import MoneyDB from './MoneyDB';
import PostMoney from './PostMoney';
import InsertCat from './InsertCat';
function MainScreen({ navigation }) {
const [number, onChangeNumber] = React.useState(null);
......@@ -25,8 +25,8 @@ function MainScreen({ navigation }) {
<Button
title="월별 페이지로 이동"
onPress={() => navigation.navigate('Monthly')}
/>
<MoneyDB />
/>
<InsertCat />
</>
)
}
......
import { DEBUG, enablePromise, openDatabase } from 'react-native-sqlite-storage';
import { SafeAreaView, StyleSheet, Text, View, TextInput, FlatList, Button } from 'react-native';
import React, { useEffect, useState } from 'react';
DEBUG(true);
enablePromise(true);
const db = openDatabase({
name: 'MyMoney',
location: 'default',
createFromLocation: '~MyMoney.db', // android/src/main/assets/TestDB.db 파일을 위치 시킴
});
const QueryFunc = async (Query) => {
(await db).transaction(Query)
};
function InsertCat() {
const [cat, setCat] = useState('')
const [asset, setAsset] = useState('')
console.log('money db')
const populateDatabase = async DB => {
await DB.transaction(queryMoney); // 반드시 (await db)를 해야 프라미스가 성공
};
const loadAndQueryDB = async () => {
try {
console.log('load and db query ....');
await populateDatabase(await db);
} catch (error) {
console.log(error);
}
};
const insertCategory = async () => {
QueryFunc(async (tx) => {
console.log("카테고리 정보 저장");
await tx.executeSql('INSERT INTO categories (category_name) VALUES (?);',
[cat],
() => { console.log("카테고리 삽입 성공"); },
(error) => console.log(error))
})
}
const insertAsset = async () => {
QueryFunc(async (tx) => {
console.log("자산 정보 저장");
await tx.executeSql('INSERT INTO assets_type (assets_name) VALUES (?);',
[asset],
() => { console.log("자산 삽입 성공"); },
(error) => console.log(error))
})
}
return (
<SafeAreaView>
<Text>db test</Text>
<View>
<Text style={style.Font}>-데이터 입력 테스트</Text>
<Text>cat</Text>
<TextInput
placeholder="cat"
onChangeText={
(cat) => setCat(cat)
}
/>
<Text>asset</Text>
<TextInput
placeholder="asset"
onChangeText={
(asset) => setAsset(asset)
}
/>
</View>
<Button title='카테고리 삽입하기' onPress={insertCategory} />
<Button title='자산 삽입하기' onPress={insertAsset} />
</SafeAreaView>
);
}
const style = StyleSheet.create({
Font: {
fontSize: 24
}
});
export default InsertCat
\ No newline at end of file
import { DEBUG, enablePromise, openDatabase } from 'react-native-sqlite-storage';
import { SafeAreaView, StyleSheet, Text, View, TextInput, FlatList, Button } from 'react-native';
import React, { useEffect, useState } from 'react';
DEBUG(true);
enablePromise(true);
......@@ -11,151 +9,12 @@ const db = openDatabase({
createFromLocation: '~MyMoney.db', // android/src/main/assets/TestDB.db 파일을 위치 시킴
});
function MoneyDB() {
const [money, setMoney] = useState([]);
const [expense, setExpense] = useState(0)
const [income, setIncome] = useState(0)
const QueryFunc = async (Query) => {
(await db).transaction(Query)
};
console.log('money db')
const populateDatabase = async DB => {
await DB.transaction(queryMoney); // 반드시 (await db)를 해야 프라미스가 성공
};
const loadAndQueryDB = async () => {
try {
console.log('load and db query ....');
await populateDatabase(await db);
} catch (error) {
console.log(error);
}
};
const closeDatabase = async DB => {
if (DB) {
console.log('closing database ...');
try {
(await DB).close(
() => {
console.log('Database was closed successfully');
},
err => console.log(err),
);
} catch (error) {
console.log(error);
}
} else {
console.log('Database was not opened');
}
};
const queryMoney = async tx => {
console.log('Excuting user query');
try {
const [txn, results] = await tx.executeSql('SELECT * FROM Money');
console.log('item length', results.rows.length);
const temp = [];
for (let i = 0; i < results.rows.length; i++) {
const element = results.rows.item(i);
temp.push(element);
console.log('item ', element);
}
setMoney(temp);
} catch (error) {
console.log('error in query money', error);
}
};
const insertData = async () => {
try {
(await db).transaction((tx) => {
console.log("데이터 삽입하기");
tx.executeSql('INSERT INTO Money (expense, income) VALUES (?,?);',
[expense, income],
() => { console.log("삽입 성공"); },
(error) => console.log(error))
})
} catch (error) {
console.log('error in insert data', error)
}
}
//수정 전 코드
// const insertData = async () => {
// await db.transaction(async (tx) => {
// console.log("데이터 삽입하기");
// tx.executeSql('INSERT INTO Money (expense, income) VALUES (?,?);',
// [expense, income],
// () => { console.log("삽입 성공"); },
// (error) => console.log(error))
// })
// }
useEffect(() => {
loadAndQueryDB();
return () => {
// closeDatabase(await db); // 컴포넌트 없어질 때 디비 닫기 Error!!!
};
}, []);
let listViewItemSeparator = () => {
return (
<View style={{ height: 0.2, width: '100%', backgroundColor: '#808080' }} />
);
};
let listItemView = item => {
console.log('item in list view', item);
return (
<View>
<Text>Expense: {item.expense} Age: {item.income}</Text>
</View>
);
};
console.log('money', money);
console.log(expense, income)
return (
<SafeAreaView>
<Text>db test</Text>
<View>
<Text style={style.Font}>-데이터 입력 테스트</Text>
<Text>expense</Text>
<TextInput
placeholder="expense"
onChangeText={
(expense) => setExpense(expense)
}
/>
<Text>income</Text>
<TextInput
placeholder="income"
onChangeText={
(income) => setIncome(income)
}
/>
<Button title='데이터 삽입하기' onPress={insertData} />
</View>
<View style={{ backgroundColor: 'gray' }}>
<Text style={style.Font}>-데이터</Text>
<View>
<FlatList
data={money}
ItemSeparatorComponent={listViewItemSeparator}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => listItemView(item)}
/>
</View>
<Button title='데이터 다시 불러오기' onPress={loadAndQueryDB} />
</View>
</SafeAreaView>
);
const moneyApi = {
QueryFunc,
}
const style = StyleSheet.create({
Font: {
fontSize: 24
}
});
export default MoneyDB
\ No newline at end of file
export default moneyApi
\ No newline at end of file
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, Button } from 'react-native';
import { DEBUG, enablePromise, openDatabase } from 'react-native-sqlite-storage';
import InputBox from './components/InputBox';
import ButtonsForm from './components/ButtonsForm';
import SelectForm from './components/SelectForm';
import StyledButton from './components/StyledButton';
import DatePicker from './components/DatePicker';
import moneyApi from './MoneyDB';
DEBUG(true);
enablePromise(true);
const db = openDatabase({
name: 'MyMoney',
location: 'default',
createFromLocation: '~MyMoney.db', // android/src/main/assets/TestDB.db 파일을 위치 시킴
name: 'MyMoney',
location: 'default',
createFromLocation: '~MyMoney.db', // android/src/main/assets/TestDB.db 파일을 위치 시킴
});
const INIT_ASSET_TYPE = [
const getDate = () => {
var date = new Date();
return (String(date.toJSON()).split(/T/)[0])
}
const INIT_SUBCATEGORIES = [
{
asset_id: '1',
asset_name: '농협',
id: 1,
value: '간식',
foreign_id: 1
},
{
asset_id: '2',
asset_name: '신한',
id: 2,
value: '외식',
foreign_id: 1
},
]
const INIT_CATEGORIES = [
{
category_id: '1',
category_name: '식비',
id: 3,
value: '배달',
foreign_id: 1
},
{
category_id: '2',
category_name: '문화',
id: 4,
value: '택시',
foreign_id: 2
},
{
category_id: '3',
category_name: '교통비',
id: 5,
value: '영화',
foreign_id: 3
},
{
category_id: '4',
category_name: '기타',
id: 6,
value: '뮤지컬',
foreign_id: 3
},
]
const PostMoney = () => {
const [selectedIndex, setSelectedIndex] = useState(0)
const [date, setDate] = useState('2021-07-09')
const [date, setDate] = useState(getDate())
const [contents, setContents] = useState('')
const [price, setPrice] = useState(0)
const [asset_type, setAsset_type] = useState(INIT_ASSET_TYPE)
const [selected_asset_type, setSelected_asset_type] = useState(INIT_ASSET_TYPE[0])
const [categories, setCategories] = useState(INIT_CATEGORIES)
const [selected_cat, setSelected_cat] = useState(INIT_CATEGORIES[0])
const [asset_type, setAsset_type] = useState([])
const [selected_asset_type, setSelected_asset_type] = useState(0)
const [categories, setCategories] = useState([])
const [selected_cat, setSelected_cat] = useState(0)
const [subcategories, setSubcategories] = useState(INIT_SUBCATEGORIES)
const [selected_subcat, setSelected_subcat] = useState(0)
console.log('입력 데이터 : ', selectedIndex, contents, price, selected_asset_type, selected_cat)
console.log('type: ', selectedIndex, '| date: ', date, '| contents: ', contents, '| price: ', price, '| selected_asset_type: ', selected_asset_type, '| selected_cat: ', selected_cat, '| selected_subcat: ', selected_subcat)
const insertData = async () => {
try {
if (selectedIndex === 0) {type = '수입'}
else if (selectedIndex === 1) {type = '지출'}
else {type = '이동'}
let type = ''
if (selectedIndex === 0) { type = '수입' }
else if (selectedIndex === 1) { type = '지출' }
else { type = '이동' }
(await db).transaction((tx) => {
console.log("데이터 삽입하기");
tx.executeSql('INSERT INTO Money (type, date, contents, price, asset_type, category, subcategory) VALUES (?,?,?,?,?,?,?);',
[type, date, contents, price, selected_asset_type, selected_cat, selected_subcat],
() => { console.log("삽입 성공"); },
(error) => console.log(error))
})
} catch (error) {
console.log('error in insert data', error)
}
}
const loadCat = async () => {
try {
await moneyApi.QueryFunc(async (tx) => {
console.log("카테고리 부르기");
const [txn, results] = await tx.executeSql('SELECT * FROM categories');
console.log('item length', results.rows.length);
const temp = [];
for (let i = 0; i < results.rows.length; i++) {
const tempId = results.rows.item(i).category_id;
const tempName = results.rows.item(i).category_name;
temp.push({ id: tempId, value: tempName });
}
setCategories(temp);
})
} catch (error) {
console.log('error in load data ( postMoney.js )', error)
}
}
(await db).transaction((tx) => {
console.log("데이터 삽입하기");
tx.executeSql('INSERT INTO Money (type, date, contents, price, asset_type, category) VALUES (?,?);',
[expense, income],
() => { console.log("삽입 성공"); },
(error) => console.log(error))
})
const loadAssetType = async () => {
try {
(await db).transaction(async (tx) => {
console.log("자산 유형 부르기");
const [txn, results] = await tx.executeSql('SELECT * FROM assets_type');
console.log('item length', results.rows.length);
const temp = [];
for (let i = 0; i < results.rows.length; i++) {
const tempId = results.rows.item(i).assets_id;
const tempName = results.rows.item(i).assets_name;
temp.push({ id: tempId, value: tempName });
}
setAsset_type(temp);
})
} catch (error) {
console.log('error in insert data', error)
console.log('error in insert data', error)
}
}
}
useEffect(() => {
loadCat()
loadAssetType()
}, [])
return (
<View>
......@@ -82,6 +139,11 @@ const PostMoney = () => {
onPress={(index) => setSelectedIndex(index)}
selectedIndex={selectedIndex}
group={["수입", "지출", "이동"]} />
<DatePicker
inputTitle="날짜"
date={date}
setDate={setDate}
/>
<InputBox
inputTitle="내용"
placeholder="내용을 입력하세요"
......@@ -101,21 +163,26 @@ const PostMoney = () => {
/>
<SelectForm
inputTitle="자산"
categories={asset_type}
selectedValue={selected_asset_type}
onValueChange={(itemValue, itemIndex) => setSelected_asset_type(itemValue)}
placeholder="자산 선택"
data={asset_type}
selectedData={selected_asset_type}
onValueChange={(assetId) => setSelected_asset_type(assetId)}
/>
<SelectForm
inputTitle="구분"
categories={categories}
selectedValue={selected_cat}
onValueChange={(itemValue, itemIndex) => setSelected_cat(itemValue)}
placeholder="카테고리 선택"
data={categories}
selectedData={selected_cat}
onValueChange={(catId) => setSelected_cat(catId)}
subData={subcategories}
selectedSubData={selected_subcat}
onSubValueChange={(subcatId) => setSelected_subcat(subcatId)}
/>
</View>
<View style={style.buttonRow}>
<StyledButton
name="저장하기"
onPress={() => console.log('저장버튼')}
onPress={insertData}
style={style.submitButton}
/>
<StyledButton
......
import { DatePickerAndroid } from 'react-native';
import React, { useState } from "react";
import { Button, View, Text, StyleSheet, Pressable } from "react-native";
import DateTimePickerModal from "react-native-modal-datetime-picker";
const DatePicker = (props) => {
const [isDatePickerVisible, setDatePickerVisibility] = useState(false);
const showDatePicker = () => {
setDatePickerVisibility(true);
};
const hideDatePicker = () => {
setDatePickerVisibility(false);
};
const handleConfirm = (date) => {
console.log("A date has been picked: ", String(date.toJSON()).split(/T/)[0]);
props.setDate(String(date.toJSON()).split(/T/)[0])
hideDatePicker();
};
return (
<View>
<Text style={{ fontSize: 18, marginLeft: 10, marginTop: 10 }}>Arrival/Departure:</Text>
<DatePicker
style={{ padding: 10 }}
date={this.state.date_in}
<View style={style.container}>
<View style={style.inputTitleArea}>
<Text style={style.inputTitle}>{props.inputTitle}</Text>
</View>
<Pressable
style={style.dateAreaStyle}
onPress={showDatePicker}>
<Text style={style.dateTextStyle}>{props.date}</Text>
</Pressable>
<DateTimePickerModal
isVisible={isDatePickerVisible}
mode="date"
format="YYYY-MM-DD"
minDate="2016-05-01"
maxDate="2016-06-01"
showIcon={false}
customStyles={{
dateInput: {
alignItems: 'flex-start',
padding: 5
},
}}
onDateChange={(date_in) => { this.setState({ date_in: date_in }); }} />
onConfirm={handleConfirm}
onCancel={hideDatePicker}
/>
</View>
);
};
const styles = StyleSheet.create({
const style = StyleSheet.create({
container: {
height:54,
flexDirection: 'row',
alignItems: "center",
marginHorizontal: 10,
marginVertical: 3,
borderWidth: 1.5,
borderStyle: "solid",
borderColor: "#1467ff",
borderRadius: 5,
backgroundColor: "#f5f5f5",
},
inputTitleArea: {
flex: 1,
},
inputTitle: {
alignSelf: "center",
color: "#1467ff",
fontSize: 20,
},
dateAreaStyle: {
flex: 3,
},
dateTextStyle: {
fontSize: 20,
},
})
export default DatePicker
\ No newline at end of file
import React, { useEffect, useRef } from 'react';
import { Animated, Text, View, StyleSheet } from 'react-native';
const Notification = (props) => {
const opacity = useRef(new Animated.Value(0)).current;
useEffect(() => {
if (props.notification !== '') {
Animated.sequence([
Animated.timing(opacity, {
toValue: 1,
duration: 500,
useNativeDriver: true,
}),
Animated.delay(2500),
Animated.timing(opacity, {
toValue: 0,
duration: 500,
useNativeDriver: true,
}),
]).start(() => {
props.setNotification('');
})
}
}, [props.notification])
return (
<View style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
}}>
<Animated.View
style={[
{
opacity: opacity
},
{
transform: [{
translateY: opacity.interpolate({
inputRange: [0, 1],
outputRange: [-20, 0],
})
}],
},
style.msgBox
]}
>
<Text style={style.textStyle}>
{props.notification}
</Text>
</Animated.View>
</View >
);
};
const style = StyleSheet.create({
msgBox: {
margin: 10,
marginBottom: 5,
backgroundColor: 'white',
padding: 15,
borderRadius: 4,
shadowColor: 'black',
shadowOffset: {
width: 0,
height: 3,
},
shadowOpacity: 0.3,
shadowRadius: 5,
elevation: 6,
},
textStyle: {
fontSize: 20
}
})
export default Notification
\ No newline at end of file
import React from 'react';
import { StyleSheet, Picker, View, Text } from 'react-native';
import { ListItem, Icon } from 'react-native-elements'
import React, { useState, useEffect } from 'react';
import { TouchableOpacity } from 'react-native';
import { StyleSheet, TouchableWithoutFeedback, View, Text, Modal, FlatList, Animated } from 'react-native';
import Notification from './Notification';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
const SelectForm = (props) => {
const [option, setOption] = useState([])
const [optionId, setOptionId] = useState(0)
const [optionValue, setOptionValue] = useState('')
const [subOption, setSubOption] = useState([])
const [subOptionId, setSubOptionId] = useState(0)
const [text, setText] = useState('')
const [subOptionShow, setSubOptionShow] = useState(false)
const [modalOpen, setModalOpen] = useState(false)
const [notification, setNotification] = useState('')
const onPressSelectBox = () => { setModalOpen(true) }
const modalClose = () => { setModalOpen(false) }
const onPressOption = (item) => {
if (subOption !== undefined) {
if (subOptionShow) {
setSubOptionId(item.id)
props.onValueChange(optionId)
props.onSubValueChange(subOptionId)
setText(optionValue + ` > ${item.value}`)
modalClose()
} else {
setOptionId(item.id)
setOptionValue(item.value)
setSubOptionByOptionId(item)
}
} else {
props.onValueChange(item.id)
setOptionId(item.id)
setOptionValue(item.value)
setText(item.value)
modalClose()
}
}
const setSubOptionByOptionId = (item) => {
const newOption = props.subData.filter((subItem) => {
if (subItem.foreign_id === item.id)
return true;
})
if (newOption.length === 0) {
setNotification(`${item.value}의 세부 카테고리가 존재하지 않습니다.`)
} else {
setSubOption(newOption)
setSubOptionShow(true)
}
}
const renderOptionItem = ({ item }) => (
<TouchableOpacity onPress={() => onPressOption(item)} style={style.option}>
<Text style={style.optionText} >
{item.value}
</Text>
</TouchableOpacity>
);
useEffect(() => {
setOption(props.data)
setSubOption(props.subData)
setSubOptionShow(false)
}, [modalOpen])
return (
<View style={styles.container}>
<View style={styles.inputTitleArea}>
<Text style={styles.inputTitle}>{props.inputTitle}</Text>
<View>
<View style={style.container}>
<View style={style.inputTitleArea}>
<Text style={style.inputTitle}>{props.inputTitle}</Text>
</View>
<View style={style.selectBox}>
<TouchableWithoutFeedback onPress={onPressSelectBox}>
<Text style={style.textStyle}>
{text ? text : props.placeholder}
</Text>
</TouchableWithoutFeedback>
</View>
</View>
<Picker
selectedValue={props.selectedValue}
style={styles.selectStyle}
onValueChange={props.onValueChange}
<Modal
transparent
swipeDirection="down"
animationType="slide"
visible={modalOpen}
onRequestClose={modalClose}
>
{props.categories.map((index, item)=>{
return(
<Picker.Item label={item.category_name} value={item.category_name} />
)
})}
</Picker>
<View style={style.selectModalContainer}>
<TouchableWithoutFeedback onPress={modalClose}>
<View style={{ flex: 1 }}>
<Notification notification={notification} setNotification={setNotification} />
</View>
</TouchableWithoutFeedback>
<View style={style.selectModal}>
<View style={style.modalHeader}>
{subOptionShow ?
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }} >
<MaterialCommunityIcons name='arrow-left' size={35} color='white' onPress={() => { setSubOptionShow(false); }} />
<Text style={style.modalHeaderText}>{optionValue}</Text>
</View>
:
<Text style={style.modalHeaderText}>{props.inputTitle}</Text>}
<View style={{ flexDirection: "row" }}>
<MaterialCommunityIcons name='playlist-edit' size={35} color='white' onPress={() => console.log('카테고리 편집')} />
<MaterialCommunityIcons name='close' size={35} color='white' onPress={modalClose} />
</View>
</View>
<View style={[style.modalBody, props.backdropStyle]}>
<FlatList
data={subOptionShow ? subOption : option}
renderItem={renderOptionItem}
numColumns={3}
keyExtractor={item => item.id.toString()}
/>
</View>
</View>
</View>
</Modal>
</View>
);
};
const styles = StyleSheet.create({
const style = StyleSheet.create({
container: {
height: 50,
flexDirection: 'row',
alignItems: "center",
marginHorizontal: 10,
......@@ -47,6 +154,49 @@ const styles = StyleSheet.create({
flex: 3,
fontSize: 20,
},
selectBox: {
flex: 3,
},
textStyle: {
fontSize: 20,
},
selectModalContainer: {
flex: 1,
justifyContent: 'flex-end',
},
selectModal: {
flex: 1,
},
modalHeader: {
flex: 1,
backgroundColor: '#4f4f4f',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
modalHeaderText: {
color: 'white',
marginLeft: 25,
fontSize: 20,
},
modalBody: {
flex: 5,
flexDirection: 'row',
backgroundColor: '#f0f0f0',
},
option: {
flex: 1,
height: 50,
borderWidth: 0.8,
borderStyle: 'solid',
borderColor: '#575757',
backgroundColor: '#adadad',
justifyContent: 'center',
alignItems: 'center',
},
optionText: {
fontSize: 20,
}
})
export default SelectForm
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment