feat(App): update Finlytic Flutter app UI and blocs

This commit is contained in:
2026-08-09 21:01:46 +02:00
parent e7427b7464
commit a708d2977c
591 changed files with 1095105 additions and 0 deletions
@@ -0,0 +1,183 @@
import 'package:flutter/material.dart';
import '../../../../core/theme/app_theme.dart';
class CandleData {
final DateTime time;
final double open;
final double high;
final double low;
final double close;
CandleData({
required this.time,
required this.open,
required this.high,
required this.low,
required this.close,
});
factory CandleData.fromJson(Map<String, dynamic> json) {
return CandleData(
time: json['timestamp'] != null ? DateTime.parse(json['timestamp'].toString()) : DateTime.now(),
open: (json['open'] as num? ?? 0.0).toDouble(),
high: (json['high'] as num? ?? 0.0).toDouble(),
low: (json['low'] as num? ?? 0.0).toDouble(),
close: (json['close'] as num? ?? 0.0).toDouble(),
);
}
}
class CandleChartWidget extends StatelessWidget {
final List<CandleData> candles;
final double? supportLevel;
final double? resistanceLevel;
const CandleChartWidget({
super.key,
this.candles = const [],
this.supportLevel,
this.resistanceLevel,
});
@override
Widget build(BuildContext context) {
if (candles.isEmpty) {
return Container(
color: AppTheme.cardSurface,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.show_chart, color: AppTheme.textMuted, size: 48),
const SizedBox(height: 12),
Text(
'Keine Candlestick-Daten verfgbar',
style: TextStyle(color: AppTheme.textMuted, fontSize: 13),
),
],
),
),
);
}
return Container(
color: Colors.black.withValues(alpha: 0.6),
padding: const EdgeInsets.all(12),
child: CustomPaint(
painter: _CandlePainter(
candles: candles,
supportLevel: supportLevel,
resistanceLevel: resistanceLevel,
),
child: Container(),
),
);
}
}
class _CandlePainter extends CustomPainter {
final List<CandleData> candles;
final double? supportLevel;
final double? resistanceLevel;
_CandlePainter({
required this.candles,
this.supportLevel,
this.resistanceLevel,
});
@override
void paint(Canvas canvas, Size size) {
if (candles.isEmpty) return;
double minPrice = candles.first.low;
double maxPrice = candles.first.high;
for (var c in candles) {
if (c.low < minPrice) minPrice = c.low;
if (c.high > maxPrice) maxPrice = c.high;
}
if (supportLevel != null && supportLevel! < minPrice) minPrice = supportLevel!;
if (resistanceLevel != null && resistanceLevel! > maxPrice) maxPrice = resistanceLevel!;
final priceRange = (maxPrice - minPrice) == 0 ? 1.0 : (maxPrice - minPrice);
final padding = size.height * 0.05;
final usableHeight = size.height - (padding * 2);
double getY(double price) {
final normalized = (price - minPrice) / priceRange;
return size.height - padding - (normalized * usableHeight);
}
// Gridlines
final gridPaint = Paint()
..color = Colors.white10
..strokeWidth = 1;
for (int i = 1; i <= 4; i++) {
final y = size.height * (i / 5);
canvas.drawLine(Offset(0, y), Offset(size.width, y), gridPaint);
}
// Support Line
if (supportLevel != null) {
final supPaint = Paint()
..color = AppTheme.primaryEmerald.withValues(alpha: 0.6)
..strokeWidth = 1.5
..style = PaintingStyle.stroke;
final y = getY(supportLevel!);
canvas.drawLine(Offset(0, y), Offset(size.width, y), supPaint);
}
// Resistance Line
if (resistanceLevel != null) {
final resPaint = Paint()
..color = AppTheme.accentRed.withValues(alpha: 0.6)
..strokeWidth = 1.5
..style = PaintingStyle.stroke;
final y = getY(resistanceLevel!);
canvas.drawLine(Offset(0, y), Offset(size.width, y), resPaint);
}
// Candlesticks
final candleWidth = (size.width / candles.length) * 0.7;
final candleSpacing = size.width / candles.length;
for (int i = 0; i < candles.length; i++) {
final candle = candles[i];
final x = (i * candleSpacing) + (candleSpacing / 2);
final isBullish = candle.close >= candle.open;
final candleColor = isBullish ? AppTheme.primaryEmerald : AppTheme.accentRed;
final wickPaint = Paint()
..color = candleColor
..strokeWidth = 1.5;
final highY = getY(candle.high);
final lowY = getY(candle.low);
canvas.drawLine(Offset(x, highY), Offset(x, lowY), wickPaint);
final openY = getY(candle.open);
final closeY = getY(candle.close);
final topY = openY < closeY ? openY : closeY;
final bodyHeight = (openY - closeY).abs();
final bodyPaint = Paint()
..color = candleColor
..style = PaintingStyle.fill;
canvas.drawRect(
Rect.fromLTWH(
x - (candleWidth / 2),
topY,
candleWidth,
bodyHeight < 1 ? 1 : bodyHeight,
),
bodyPaint,
);
}
}
@override
bool shouldRepaint(covariant _CandlePainter oldDelegate) => true;
}