import React, { useState, useEffect, useCallback } from 'react';
import {
StyleSheet,
View,
Text,
TouchableOpacity,
ActivityIndicator,
ScrollView,
useWindowDimensions,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { BarChart } from 'react-native-gifted-charts';
const API_BASE_URL = 'https://solorpower.dadot.net';
export default function ComparisonScreen({ navigation }) {
const [period, setPeriod] = useState('day');
const [statsData, setStatsData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [currentDate, setCurrentDate] = useState(new Date());
const { width } = useWindowDimensions();
useEffect(() => {
setCurrentDate(new Date());
}, [period]);
const moveDate = (direction) => {
const newDate = new Date(currentDate);
if (period === 'day') {
newDate.setDate(newDate.getDate() + direction);
} else if (period === 'month') {
newDate.setMonth(newDate.getMonth() + direction);
} else if (period === 'year') {
newDate.setFullYear(newDate.getFullYear() + direction);
}
setCurrentDate(newDate);
};
const formatDateDisplay = () => {
const y = currentDate.getFullYear();
const m = currentDate.getMonth() + 1;
const d = currentDate.getDate();
if (period === 'day') return `${y}년 ${m}월 ${d}일`;
if (period === 'month') return `${y}년 ${m}월`;
if (period === 'year') return `${y}년`;
return '';
};
const fetchStats = useCallback(async () => {
try {
setLoading(true);
setError(null);
const y = currentDate.getFullYear();
const m = currentDate.getMonth() + 1;
const d = currentDate.getDate();
const dateStr = `${y}-${String(m).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
let query = `period=${period}`;
if (period === 'day') {
query += `&date=${dateStr}`;
} else if (period === 'month') {
query += `&year=${y}&month=${m}`;
} else if (period === 'year') {
query += `&year=${y}`;
}
const response = await fetch(`${API_BASE_URL}/plants/stats/comparison?${query}`);
if (!response.ok) throw new Error(`HTTP Error: ${response.status}`);
const result = await response.json();
setStatsData(result.data || []);
} catch (err) {
setError(err.message);
setStatsData([]);
} finally {
setLoading(false);
}
}, [period, currentDate]);
useEffect(() => {
fetchStats();
}, [fetchStats]);
// Chart Data Preparation
const chartData = statsData.map(item => {
let label = item.plant_name;
const match = label.match(/(\d+호기)/);
if (match) {
label = match[1];
} else {
label = label.replace(/태양과바람|발전소/g, '').trim();
}
return {
value: item.generation,
label: label,
frontColor: '#3B82F6',
topLabelComponent: () => (
{item.generation.toFixed(0)}
),
};
});
const renderTabs = () => (
{['day', 'month', 'year'].map((p) => (
setPeriod(p)}
>
{p === 'day' ? '일간' : p === 'month' ? '월간' : '연간'}
))}
);
const renderDateControl = () => (
moveDate(-1)} style={styles.arrowButton}>
◀
{formatDateDisplay()}
moveDate(1)} style={styles.arrowButton}>
▶
);
const renderTable = () => (
발전소
발전량
용량
시간
{statsData.map((item, index) => (
{item.plant_name}
{item.generation.toFixed(1)}
{item.capacity}
{item.generation_hours.toFixed(2)}
))}
{statsData.length === 0 && (
데이터가 없습니다
)}
);
const chartWidth = width - 40;
return (
navigation.goBack()}>
← 뒤로
전체 발전소 비교
{renderDateControl()}
{renderTabs()}
{loading ? (
데이터 불러오는 중...
) : error ? (
데이터 조회 실패
{error}
다시 시도
) : (
<>
📊 발전량 비교 (kWh)
{statsData.length > 0 ? (
) : (
표시할 데이터가 없습니다.
)}
📋 상세 현황
시간 = 발전량 / 설비용량 {period === 'year' ? '/ 365' : ''}
{renderTable()}
>
)}
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F3F4F6',
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#1E40AF',
padding: 16,
},
backButton: {
padding: 8,
},
backButtonText: {
color: '#FFFFFF',
fontSize: 16,
fontWeight: '500',
},
headerTitle: {
fontSize: 18,
fontWeight: 'bold',
color: '#FFFFFF',
},
content: {
flex: 1,
},
scrollContent: {
padding: 16,
paddingBottom: 40,
},
dateControl: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 16,
gap: 16,
},
arrowButton: {
padding: 8,
},
arrowText: {
fontSize: 20,
color: '#4B5563',
},
dateText: {
fontSize: 18,
fontWeight: 'bold',
color: '#1F2937',
},
tabContainer: {
flexDirection: 'row',
backgroundColor: '#FFFFFF',
borderRadius: 12,
padding: 4,
marginBottom: 16,
shadowColor: '#000',
shadowOpacity: 0.05,
shadowRadius: 4,
elevation: 2,
},
tab: {
flex: 1,
paddingVertical: 10,
alignItems: 'center',
borderRadius: 8,
},
tabActive: {
backgroundColor: '#3B82F6',
},
tabText: {
fontSize: 14,
fontWeight: '600',
color: '#6B7280',
},
tabTextActive: {
color: '#FFFFFF',
},
loadingContainer: {
height: 300,
justifyContent: 'center',
alignItems: 'center',
},
loadingText: {
marginTop: 12,
color: '#6B7280',
},
errorContainer: {
height: 300,
justifyContent: 'center',
alignItems: 'center',
},
errorText: {
fontSize: 16,
color: '#EF4444',
marginBottom: 8,
},
errorDetail: {
fontSize: 12,
color: '#6B7280',
marginBottom: 16,
},
retryButton: {
backgroundColor: '#3B82F6',
paddingHorizontal: 20,
paddingVertical: 10,
borderRadius: 8,
},
retryButtonText: {
color: '#FFFFFF',
},
chartSection: {
backgroundColor: '#FFFFFF',
borderRadius: 16,
padding: 16,
marginBottom: 16,
shadowColor: '#000',
shadowOpacity: 0.05,
shadowRadius: 8,
elevation: 2,
},
sectionTitle: {
fontSize: 16,
fontWeight: 'bold',
color: '#1F2937',
marginBottom: 12,
},
chartContainer: {
alignItems: 'center',
paddingVertical: 10,
},
noDataText: {
color: '#9CA3AF',
marginVertical: 20,
},
tableSection: {
backgroundColor: '#FFFFFF',
borderRadius: 16,
padding: 16,
shadowColor: '#000',
shadowOpacity: 0.05,
shadowRadius: 8,
elevation: 2,
},
tableHeaderRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 12,
},
unitText: {
fontSize: 11,
color: '#6B7280',
},
table: {
borderWidth: 1,
borderColor: '#E5E7EB',
borderRadius: 8,
overflow: 'hidden',
},
tableHeader: {
flexDirection: 'row',
backgroundColor: '#F3F4F6',
paddingVertical: 10,
paddingHorizontal: 8,
borderBottomWidth: 1,
borderBottomColor: '#E5E7EB',
},
columnHeader: {
fontSize: 12,
fontWeight: 'bold',
color: '#4B5563',
textAlign: 'center',
},
tableRow: {
flexDirection: 'row',
paddingVertical: 12,
paddingHorizontal: 8,
borderBottomWidth: 1,
borderBottomColor: '#E5E7EB',
},
tableRowAlt: {
backgroundColor: '#F9FAFB',
},
cell: {
fontSize: 12,
color: '#1F2937',
textAlign: 'center',
},
emptyRow: {
padding: 20,
alignItems: 'center',
},
emptyText: {
color: '#9CA3AF',
fontSize: 14,
},
});