Commit ef8f183e authored by Choi Ga Young's avatar Choi Ga Young
Browse files

캘린더, 차트페이지 기능구현 및 DB연결완료

parent a1638f81
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { SafeAreaView, FlatList, View, Text, StyleSheet, Dimensions } from 'react-native'; import ChartM from './ChartM';
import ChartY from './ChartY';
import chartApi from './db/chartData.api'; import chartApi from './db/chartData.api';
import { import ButtonsForm from './components/ButtonsForm';
LineChart, import { View, Dimensions } from 'react-native';
BarChart,
PieChart,
ProgressChart,
ContributionGraph,
StackedBarChart
} from "react-native-chart-kit";
const screenWidth = Dimensions.get("window").width; const screenWidth = Dimensions.get("window").width;
const screenHeight = Dimensions.get("window").height;
const data1 = [
{
name: "Seoul",
population: 21500000,
color: "rgba(131, 167, 234, 1)",
legendFontColor: "#7F7F7F",
legendFontSize: 15
},
{
name: "Toronto",
population: 2800000,
color: "#d8bfd8",
legendFontColor: "#7F7F7F",
legendFontSize: 15
},
{
name: "Beijing",
population: 1276120,
color: "#87ceeb",
legendFontColor: "#7F7F7F",
legendFontSize: 15
},
{
name: "New York",
population: 8538000,
color: "#fff5ee",
legendFontColor: "#7F7F7F",
legendFontSize: 15
},
{
name: "Moscow",
population: 11920000,
color: "#b0c4de",
legendFontColor: "#7F7F7F",
legendFontSize: 15
}
];
const data2 = {
labels: ["Jan", "Feb", "Mar", "April", "May", "June"],
datasets: [
{
data: [20, 45, 28, 80, 99, 43]
}
]
};
const ChartItem = ({ item }) => {
return (
<>
<View style={{
flexDirection: "row", padding: "5%", borderColor: '#d3d3d3', //light grey
borderWidth: 1, borderTopWidth: 0,
}}>
<Text style={[style.itemText, style.Font]}>{item.name}</Text>
<Text style={[style.itemText, style.Font]}>{item.total}</Text>
<Text></Text>
</View>
</>
);
};
const Analy = () => { const Analy = () => {
const chartConfig = { const date = new Date();
backgroundGradientFrom: "#abbcd6", //좌측 색 const [year, setYear] = useState(date.getFullYear());
backgroundGradientFromOpacity: 0.5, const [month, setMonth] = useState(date.getMonth());
backgroundGradientTo: "#E6DDC5", // 우측 색 const [resDataM, setResDataM] = useState([]);
backgroundGradientToOpacity: 0.2, const [resDataY, setResDataY] = useState([]);
backgroundColor: "#ffffff", // 어디에 적용된건지 잘 모르겠음 const [selectedIndex, setSelectedIndex] = useState(0);
color: (opacity = 1) => `rgba(0, 93, 232, ${opacity})`, // data의 색상 계산할 때 사용하는 함수
//color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
strokeWidth: 2, // optional, default 3
barPercentage: 0.5, // 그래프 width
useShadowColorFromDataset: false,// optional, default is false
//fillShadowGradient: 'blue',
fillShadowGradientOpacity: 1, // 좀 더 진하게만 할 뿐 단색 설정은 못하는 것 같음
}; const getDataM = async () => {
const [resData, setResData] = useState([])
const getData = async () => {
try { try {
const resdata = await chartApi.outMoney({ year: 2021, month: 6 }) const resdata = await chartApi.outMoney({ year: year, month: month })
console.log('db res', resdata) console.log('db res M', resdata)
setResData(resdata) return resdata
} catch (error) { } catch (error) {
console.log('error in getData', error) console.log('error in getDataM', error)
} }
} }
const renderChart = ({ item }) => { const getDataY = async () => {
return ( try {
<ChartItem item={item} /> const resdata = await chartApi.yearMoney({ year: year })
) console.log('db res Y', resdata)
setResDataY(resdata)
} catch (error) {
console.log('error in getDataY', error)
}
} }
const calPercentage = async () => {
const resPrice = await getDataM()
//console.log('어떻게 생겼니', resPrice)
let totalP = 0;
for (let i = 0; i < resPrice.length; i++) {
totalP = totalP + resPrice[i].total;
}
for (let j = 0; j < resPrice.length; j++) {
resPrice[j].percentage = Math.round((resPrice[j].total / totalP) * 100);
}
setResDataM(resPrice)
}
useEffect(() => { useEffect(() => {
getData() getDataY()
calPercentage()
}, []) }, [])
useEffect(() => {
setResDataM([])
calPercentage()
}, [month])
useEffect(() => {
getDataY()
}, [year])
return ( return (
<View> <>
<Text style={style.Font}>여기는 분석 페이지/ 차트 테스트</Text> <View>
<PieChart <ButtonsForm
data={resData} onPress={(index) => setSelectedIndex(index)}
width={screenWidth} selectedIndex={selectedIndex}
height={screenHeight / 3} //그래프의 높이가 커지기만 group={["월간", "연간"]} />
chartConfig={chartConfig} </View>
accessor={"total"} <View>
backgroundColor={"#ffffff"} {
// paddingLeft={"15"} selectedIndex === 0 ? <ChartM resDataM={resDataM} year={year} setYear={setYear} month={month} setMonth={setMonth} /> : <ChartY resDataY={resDataY} year={year} setYear={setYear} />
// center={[10, 50]} }
absolute </View>
/> </>
<FlatList
style={{ backgroundColor: "#FFFFFF" }}
data={resData}
renderItem={renderChart}
keyExtractor={item => item.category}
/>
{/* <BarChart
//style={graphStyle}
data={data2}
width={screenWidth}
height={screenHeight / 3}
//yAxisLabel="$"
chartConfig={chartConfig}
//verticalLabelRotation={30}
/> */}
</View>
) )
} }
const style = StyleSheet.create({
Font: {
fontSize: 20
},
itemText: {
paddingRight: "10%",
// paddingLeft: "20%",
// alignItems:"center"
}
});
export default Analy; export default Analy;
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import { FlatList, View, Text, StyleSheet, Dimensions } from 'react-native';
import { Button } from 'react-native-elements';
import Ionicons from 'react-native-vector-icons/Ionicons';
import { PieChart } from "react-native-chart-kit";
const screenWidth = Dimensions.get("window").width;
const screenHeight = Dimensions.get("window").height;
const ChartItem = ({ item }) => {
return (
<>
<View style={{
flexDirection: "row", padding: "5%", borderColor: '#d3d3d3', //light grey
borderWidth: 1, borderTopWidth: 0,
}}>
<Text style={[style.itemText, style.Font]}>{item.name}</Text>
<Text style={[style.itemText, style.Font]}>{item.total}</Text>
<Text style={[style.itemText, style.Font]}>{item.percentage}%</Text>
<Text></Text>
</View>
</>
);
};
const ChartM = ({
resDataM,
year,
setYear,
month,
setMonth
}) => {
const chartConfig = {
backgroundGradientFrom: "#abbcd6", //좌측 색
backgroundGradientFromOpacity: 0.5,
backgroundGradientTo: "#E6DDC5", // 우측 색
backgroundGradientToOpacity: 0.2,
backgroundColor: "#ffffff", // 어디에 적용된건지 잘 모르겠음
color: (opacity = 1) => `rgba(0, 93, 232, ${opacity})`, // data의 색상 계산할 때 사용하는 함수
//color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
strokeWidth: 2, // optional, default 3
barPercentage: 0.5, // 그래프 width
useShadowColorFromDataset: false,// optional, default is false
//fillShadowGradient: 'blue',
fillShadowGradientOpacity: 1, // 좀 더 진하게만 할 뿐 단색 설정은 못하는 것 같음
};
const renderChart = ({ item }) => {
return (
<ChartItem item={item} />
)
}
const prevBtn = () => {
if (month < 1) {
setYear(year - 1)
setMonth(11)
} else {
setMonth(month - 1)
}
};
const nextBtn = () => {
if (month > 10) {
setYear(year + 1)
setMonth(0)
} else {
setMonth(month + 1)
}
}
console.log('sdfaslfsakflf', resDataM)
return (
<>
<View style={{ flexDirection: 'row' }}>
<Button icon={
<Ionicons name='chevron-back-sharp' onPress={prevBtn} size={15} color='black' />
} type='clear' />
<Text>{year}.{month + 1}</Text>
<Button icon={
<Ionicons name='chevron-forward-sharp' onPress={nextBtn} size={15} color='black' />
} type='clear' />
</View>
<View>
{
resDataM.length != 0 ?
< PieChart
data={resDataM}
width={screenWidth}
height={screenHeight / 3} //그래프의 높이가 커지기만
chartConfig={chartConfig}
accessor={"total"}
backgroundColor={"#ffffff"}
absolute
/> : <Text style={{ fontSize: 30, textAlign: "center" }}> 지출 내역이 없습니다.</Text>
}
<FlatList
style={{ backgroundColor: "#FFFFFF" }}
data={resDataM}
renderItem={renderChart}
keyExtractor={item => item.color}
/>
</View>
</>
)
}
const style = StyleSheet.create({
Font: {
fontSize: 20
},
itemText: {
paddingRight: "10%"
}
});
export default ChartM;
\ No newline at end of file
import React from 'react';
import { View, Text, StyleSheet, Dimensions } from 'react-native';
import { BarChart } from "react-native-chart-kit";
import { Button } from 'react-native-elements';
import Ionicons from 'react-native-vector-icons/Ionicons';
const screenWidth = Dimensions.get("window").width;
const screenHeight = Dimensions.get("window").height;
const ChartY = ({ resDataY, year, setYear }) => {
const chartConfig = {
backgroundGradientFrom: "#ffffff", //좌측 색
backgroundGradientFromOpacity: 1,
backgroundGradientTo: "#ffffff", // 우측 색
backgroundGradientToOpacity: 1,
color: (opacity = 1) => `rgba(48, 48, 48, ${opacity})`,
strokeWidth: 2, // optional, default 3
barPercentage: 0.5, // 그래프 width
useShadowColorFromDataset: false,// optional, default is false
fillShadowGradientOpacity: 1, // 좀 더 진하게만 할 뿐 단색 설정은 못하는 것 같음
};
const prevBtn = () => {
setYear(year - 1)
};
const nextBtn = () => {
setYear(year + 1)
}
console.log('잠만확인', resDataY.temp1[0].datasets[0].data, '|', resDataY.temp2[0].datasets[0].data)
let totalYI = (resDataY.temp1[0].datasets[0].data).reduce((acc, curr) => acc + curr, 0);
let totalYO = (resDataY.temp2[0].datasets[0].data).reduce((acc, curr) => acc + curr, 0);
console.log('합산 확인', totalYI, '|', totalYO)
return (
<>
<View style={{ flexDirection: 'row' }}>
<Button icon={
<Ionicons name='chevron-back-sharp' onPress={prevBtn} size={15} color='black' />
} type='clear' />
<Text>{year}</Text>
<Button icon={
<Ionicons name='chevron-forward-sharp' onPress={nextBtn} size={15} color='black' />
} type='clear' />
</View>
<View>
<Text style={style.Font}>수입: {totalYI}</Text>
<BarChart
style={{ marginBottom: "2%", marginTop: "2%" }}
data={resDataY.temp1[0]}
width={screenWidth}
height={screenHeight / 3}
chartConfig={{ ...chartConfig, fillShadowGradient: '#1E90FF' }}
fromZero={true}
/>
<Text style={style.Font}>지출: {totalYO} </Text>
<BarChart
style={{ marginTop: "2%" }}
data={resDataY.temp2[0]}
width={screenWidth}
height={screenHeight / 3}
chartConfig={{ ...chartConfig, fillShadowGradient: '#DC143C' }}
fromZero={true}
/>
</View>
</>
)
}
const style = StyleSheet.create({
Font: {
textAlign: "center",
fontSize: 20,
fontFamily: 'Jua-Regular'
},
});
export default ChartY;
\ No newline at end of file
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, FlatList, TextComponent } from 'react-native'; import { SafeAreaView, View, Text, StyleSheet, FlatList } from 'react-native';
import calApi from './db/calendarInfo.api'; import calApi from './db/calendarInfo.api';
const DetailItem = ({ item }) => { const DetailItem = ({ item }) => {
return ( return (
<>{ <>
item != [] ? <View style={{ <View style={{
flexDirection: "row", padding: "5%", borderColor: '#d3d3d3', //light grey flexDirection: "row", padding: "5%", borderColor: '#d3d3d3', //light grey
borderWidth: 1, borderTopWidth: 0, borderWidth: 1, borderTopWidth: 0,
}}> }}>
<Text style={item.type === 1 ? style.inputColor : style.outputColor}>{item.category}</Text> <Text style={item.type === 1 ? style.inputColor : style.outputColor}>{item.category}</Text>
<Text style={[style.itemText, style.Font]}>{item.contents}</Text> <Text style={[style.itemText, style.Font]}>{item.contents}</Text>
<Text style={[style.itemText, style.Font]}>{item.price}</Text> <Text style={[style.itemText, style.Font]}>{item.price}</Text>
</View> : <View>
<Text>내역이 없습니다.</Text>
</View> </View>
}
</> </>
); );
}; };
...@@ -45,11 +42,16 @@ const DetailInfo = ({ route }) => { ...@@ -45,11 +42,16 @@ const DetailInfo = ({ route }) => {
return ( return (
<> <>
<SafeAreaView> <SafeAreaView>
<FlatList {
data={resData} resData.length != 0 ? <FlatList
renderItem={renderDetail} data={resData}
keyExtractor={item => item.id} renderItem={renderDetail}
/> keyExtractor={item => item.id}
/> : <View>
<Text style={{textAlign:"center", fontSize:20}}>내역이 없습니다.</Text>
</View>
}
</SafeAreaView> </SafeAreaView>
</> </>
) )
......
...@@ -21,7 +21,7 @@ const Montly = ({ navigation }) => { ...@@ -21,7 +21,7 @@ const Montly = ({ navigation }) => {
} }
useEffect(() => { useEffect(() => {
getData() getData()
}, []) }, [month])
return ( return (
<Calendar navigation={navigation} MData={totalM} year={year} setYear={setYear} month={month} setMonth={setMonth} todayM={todayM} todayY={todayY} /> <Calendar navigation={navigation} MData={totalM} year={year} setYear={setYear} month={month} setMonth={setMonth} todayM={todayM} todayY={todayY} />
) )
......
...@@ -3,16 +3,17 @@ import { ButtonGroup } from 'react-native-elements'; ...@@ -3,16 +3,17 @@ import { ButtonGroup } from 'react-native-elements';
import { StyleSheet, Text } from 'react-native'; import { StyleSheet, Text } from 'react-native';
const ButtonsForm = (props) => { const ButtonsForm = (props) => {
const components = [];
const component1 = () => <Text>{props.group[0]}</Text> for (let i = 0; i < props.group.length ; i++) {
const component2 = () => <Text>{props.group[1]}</Text> components[i] = { element: () => <Text>{props.group[i]}</Text> }
const component3 = () => <Text>{props.group[2]}</Text> }
return ( return (
<ButtonGroup <ButtonGroup
onPress={props.onPress} onPress={props.onPress}
selectedIndex={props.selectedIndex} selectedIndex={props.selectedIndex}
buttons={[{ element: component1 }, { element: component2 }, { element: component3 }]} buttons={components}
containerStyle={style.container} containerStyle={style.container}
selectedButtonStyle={style.selectedButton} selectedButtonStyle={style.selectedButton}
selectedTextStyle={style.selectedText} selectedTextStyle={style.selectedText}
...@@ -20,6 +21,7 @@ const ButtonsForm = (props) => { ...@@ -20,6 +21,7 @@ const ButtonsForm = (props) => {
); );
}; };
const style = StyleSheet.create({ const style = StyleSheet.create({
container: { container: {
height: 50, height: 50,
......
...@@ -14,12 +14,16 @@ const getFullData = async ({ year, month }) => { ...@@ -14,12 +14,16 @@ const getFullData = async ({ year, month }) => {
console.log('월간 데이터'); console.log('월간 데이터');
const [txn, results] = await tx.executeSql(`SELECT date, type_id, sum(price) as total from money where date BETWEEN "${String(thisFirst.toJSON()).split(/T/)[0]}" and "${String(thisLast.toJSON()).split(/T/)[0]}" group by date, type_id`); const [txn, results] = await tx.executeSql(`SELECT date, type_id, sum(price) as total from money where date BETWEEN "${String(thisFirst.toJSON()).split(/T/)[0]}" and "${String(thisLast.toJSON()).split(/T/)[0]}" group by date, type_id`);
const temp = []; const temp = [];
if (results.rows.item(0).type_id === 1) { console.log('lelel', results.rows.length)
temp.push({ date: results.rows.item(0).date, type: { 'input': results.rows.item(0).total } }) if (results.rows.length != 0) {
} if (results.rows.item(0).type_id === 1) {
if (results.rows.item(0).type_id === 2) { temp.push({ date: results.rows.item(0).date, type: { 'input': results.rows.item(0).total } })
temp.push({ date: results.rows.item(0).date, type: { 'output': results.rows.item(0).total } }) }
if (results.rows.item(0).type_id === 2) {
temp.push({ date: results.rows.item(0).date, type: { 'output': results.rows.item(0).total } })
}
} }
for (let i = 1; i < results.rows.length; i++) { for (let i = 1; i < results.rows.length; i++) {
if (results.rows.item(i).date === results.rows.item(i - 1).date) { if (results.rows.item(i).date === results.rows.item(i - 1).date) {
temp.pop() temp.pop()
......
...@@ -4,6 +4,13 @@ import getDb from './moneyDB' ...@@ -4,6 +4,13 @@ import getDb from './moneyDB'
DEBUG(true); DEBUG(true);
enablePromise(true); enablePromise(true);
const colorArr = [
"#f06c77", "#ffa07a", "#fafad2", "#e3fad2", "#b0c4de",
"#49618f", "#dda0dd", "#ff4d6a", "#fcc24c", "#fffacd",
"#8fbc8f", "#82a6e9", "#2b4069", "#db7093", "#fa8072",
"#98fb98", "#d6badb"
]
const outMoney = async ({ year, month }) => { const outMoney = async ({ year, month }) => {
const thisFirst = new Date(year, month, 1); //이번 달의 첫째 날 const thisFirst = new Date(year, month, 1); //이번 달의 첫째 날
const thisLast = new Date(year, month + 1, 0); //이번 달의 마지막 날 const thisLast = new Date(year, month + 1, 0); //이번 달의 마지막 날
...@@ -12,36 +19,70 @@ const outMoney = async ({ year, month }) => { ...@@ -12,36 +19,70 @@ const outMoney = async ({ year, month }) => {
return new Promise((res, rej) => { return new Promise((res, rej) => {
db.transaction(async (tx) => { db.transaction(async (tx) => {
console.log('차트 페이지'); console.log('차트 페이지');
const [txn, results] = await tx.executeSql(`SELECT category_id, sum(price) as total from (SELECT type, price, category from money where date BETWEEN "${String(thisFirst.toJSON()).split(/T/)[0]}" and "${String(thisLast.toJSON()).split(/T/)[0]}") WHERE type='지출' group by category`); const [txn, results] = await tx.executeSql(`SELECT category_id, category_name, sum(price) as total from (SELECT money.type_id, price, money.category_id, category_name FROM money inner JOIN categories on money.category_id = categories.category_id where date BETWEEN "${String(thisFirst.toJSON()).split(/T/)[0]}" and "${String(thisLast.toJSON()).split(/T/)[0]}") WHERE type_id=2 group by category_id`);
const temp = []; const temp = [];
let totalP = 0;
for (let i = 0; i < results.rows.length; i++) { for (let i = 0; i < results.rows.length; i++) {
console.log('chart', results.rows.item(i)) console.log('chart', results.rows.item(i))
if (results.rows.item(i).category === 1) {
temp.push({ temp.push({
name: "식비", total: results.rows.item(i).total, color: "#b0c4de", legendFontColor: "#7F7F7F", name: results.rows.item(i).category_name,
legendFontSize: 15 total: results.rows.item(i).total,
}) color: colorArr[i], legendFontColor: "#7F7F7F",
} else if (results.rows.item(i).category === 2) { legendFontSize: 15
temp.push({ })
name: "교통비", total: results.rows.item(i).total, color: "#ffa07a", legendFontColor: "#7F7F7F", console.log('chart temp', temp)
legendFontSize: 15 res(temp)
})
} else if (results.rows.item(i).category === 3) {
temp.push({
name: "문화비", total: results.rows.item(i).total, color: "rgba(131, 167, 234, 1)", legendFontColor: "#7F7F7F",
legendFontSize: 15
})
}
} }
console.log('chart temp', temp)
res(temp)
}) })
}) })
} }
const yearMoney = async ({ year }) => {
const yearFirst = new Date(year, 0, 1); //1월 1일
const yearLast = new Date(year, 12, 0); //12월 31일
const db = await getDb();
console.log('year', yearFirst, '|', yearLast)
return new Promise((res, rej) => {
db.transaction(async (tx) => {
console.log('차트페이지 연간')
const [txn, results] = await tx.executeSql(`SELECT strftime('%m',date) as month, type_id, sum(price) as total from money where strftime('%Y', date)= "${year}" GROUP by strftime('%m', date), type_id `);
const temp1 = [];
const temp2 = [];
let temparr1 = new Array(12).fill(0)
let temparr2 = new Array(12).fill(0)
for (let i = 0; i < results.rows.length; i++) {
console.log('year res check', results.rows.item(i))
if (results.rows.item(i).type_id === 1) {
let idx = Number(results.rows.item(i).month)
temparr1[idx - 1] = results.rows.item(i).total
} else if (results.rows.item(i).type_id === 2) {
let idx = Number(results.rows.item(i).month)
temparr2[idx - 1] = results.rows.item(i).total
}
}
temp1.push({
labels: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
datasets: [{
data: temparr1
}]
})
temp2.push({
labels: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
datasets: [{
data: temparr2
}]
})
res({ temp1, temp2 })
})
})
}
const chartApi = { const chartApi = {
outMoney outMoney,
yearMoney
} }
export default chartApi; export default chartApi;
\ No newline at end of file
module.exports = {
project: {
ios: {},
android: {}, // grouped into "project"
},
assets: ["./assets/fonts/"], // stays the same
};
\ 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