Skip to content

Commit

Permalink
Improved UI
Browse files Browse the repository at this point in the history
  • Loading branch information
ivofernandes committed Dec 16, 2023
1 parent e2620a5 commit bb12646
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 156 deletions.
49 changes: 26 additions & 23 deletions app_modules/ticker_details/lib/src/ticker_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,33 @@ class TickerScreen extends StatelessWidget {
});

@override
Widget build(BuildContext context) => FutureBuilder<dynamic>(
future: YahooFinanceService().getTickerData(ticker.symbol),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.data == null) {
return const Center(
child: CircularProgressIndicator(),
);
}
Widget build(BuildContext context) => GestureDetector(
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: FutureBuilder<dynamic>(
future: YahooFinanceService().getTickerData(ticker.symbol),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.data == null) {
return const Center(
child: CircularProgressIndicator(),
);
}

return ChangeNotifierProvider(
create: (context) => TickerStateProvider(),
child: Consumer<TickerStateProvider>(
builder: (context, tickerState, child) {
tickerState.startAnalysis(snapshot.data as List<YahooFinanceCandleData>);
return ChangeNotifierProvider(
create: (context) => TickerStateProvider(),
child: Consumer<TickerStateProvider>(
builder: (context, tickerState, child) {
tickerState.startAnalysis(snapshot.data as List<YahooFinanceCandleData>);

return SafeArea(
child: TickerTabs(
ticker,
snapshot.data as List<YahooFinanceCandleData>,
),
);
},
),
);
},
return SafeArea(
child: TickerTabs(
ticker,
snapshot.data as List<YahooFinanceCandleData>,
),
);
},
),
);
},
),
);
}
5 changes: 5 additions & 0 deletions lib/big_picture/state/big_picture_state_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ class BigPictureStateProvider with ChangeNotifier, ConnectivityState {
}

Future<void> addTicker(StockTicker ticker) async {
// Treat multiple strategies
ticker = ticker.copyWith(
symbol: ticker.symbol.split(' ').map((String s) => s.trim()).toList().join(', '),
);

_bigPictureData[ticker] = BuyAndHoldStrategyResult();

// Get data from yahoo finance
Expand Down
35 changes: 29 additions & 6 deletions lib/big_picture/ui/resume/strategy_resume_details_ui.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,35 @@ class StrategyResumeDetails extends StatelessWidget {
final double sma20sma50 = (strategy.movingAverages[20]! / strategy.movingAverages[50]! - 1) * 100;
final double sma50sma200 = (strategy.movingAverages[50]! / strategy.movingAverages[200]! - 1) * 100;

String prefixVar20 = '';
String prefixVar50 = '';
String prefixVar200 = '';

if (!bigPictureState.isCompactView()) {
prefixVar20 = 'price/sma20';
prefixVar50 = 'sma20/sma50';
prefixVar200 = 'sma50/sma200';
}

final priceVarChip20 = PriceVariationChip(
prefix: prefixVar20,
value: pricesma20,
);
final priceVarChip50 = PriceVariationChip(
prefix: prefixVar50,
value: sma20sma50,
);
final priceVarChip200 = PriceVariationChip(
prefix: prefixVar200,
value: sma50sma200,
);

return bigPictureState.isCompactView()
? Column(
children: [
PriceVariationChip(null, pricesma20),
PriceVariationChip(null, sma20sma50),
PriceVariationChip(null, sma50sma200)
priceVarChip20,
priceVarChip50,
priceVarChip200,
],
)
: Row(
Expand Down Expand Up @@ -73,9 +96,9 @@ class StrategyResumeDetails extends StatelessWidget {
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
PriceVariationChip('price/sma20', pricesma20),
PriceVariationChip('sma20/sma50', sma20sma50),
PriceVariationChip('sma50/sma200', sma50sma200)
priceVarChip20,
priceVarChip50,
priceVarChip200,
],
)
],
Expand Down
175 changes: 110 additions & 65 deletions lib/big_picture/ui/resume/strategy_resume_header_ui.dart
Original file line number Diff line number Diff line change
@@ -1,95 +1,140 @@
import 'package:app_dependencies/app_dependencies.dart';
import 'package:flutter/material.dart';
import 'package:interactive_i18n/interactive_i18n.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:stock_market_data/stock_market_data.dart';
import 'package:td_ui/td_ui.dart';
import 'package:ticker_search/ticker_search.dart';
import 'package:turing_deal/big_picture/state/big_picture_state_provider.dart';
import 'package:turing_deal/home/home_screen.dart';

/// A widget to display the header information for a strategy resume.
///
/// This includes the stock ticker information, strategy results, and an option
/// to add more details or change the current selection.
class StrategyResumeHeader extends StatelessWidget {
final StockTicker ticker;
final BuyAndHoldStrategyResult? strategy;
final BuyAndHoldStrategyResult strategy;
final double cardWidth;

const StrategyResumeHeader(
this.ticker,
this.strategy,
this.cardWidth,
);
final double variation;

final Color color;

/// Constructs a [StrategyResumeHeader] widget.
///
/// Takes in [ticker] for stock information, [strategy] for strategy results,
/// and [cardWidth] to determine the width of the card.
const StrategyResumeHeader({
required this.ticker,
required this.strategy,
required this.cardWidth,
required this.variation,
required this.color,
super.key,
});

@override
Widget build(BuildContext context) {
final BigPictureStateProvider bigPictureState = Provider.of<BigPictureStateProvider>(context, listen: false);

final ThemeData theme = Theme.of(context);
final String tickerDescription = TickerResolve.getTickerDescription(ticker);

final String ticketDescription = TickerResolve.getTickerDescription(ticker);
final double titleWidth = bigPictureState.isCompactView() ? cardWidth - 30 : cardWidth / 2 - 20;

final TickerSearch tickerSearch = TickerSearch(searchFieldLabel: 'Add'.t, suggestions: HomeScreen.suggestions);
final PriceVariationChip priceVariationChip = PriceVariationChip(
value: variation,
minColor: theme.colorScheme.error,
maxColor: theme.colorScheme.primary,
minValue: -2.5,
maxValue: 2.5,
);

return Stack(
alignment: Alignment.topCenter,
children: [
Column(children: [
Row(
mainAxisAlignment:
bigPictureState.isCompactView() ? MainAxisAlignment.center : MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: bigPictureState.isCompactView() ? cardWidth - 30 : cardWidth / 2 - 20,
child: Text(
ticker.symbol,
style: theme.textTheme.titleLarge,
textAlign: bigPictureState.isCompactView() ? TextAlign.center : TextAlign.start,
),
),
bigPictureState.isCompactView()
? Container()
: SizedBox(
width: cardWidth / 2 - 20,
child: Align(
alignment: Alignment.centerRight,
child: Text(ticketDescription, style: theme.textTheme.bodyLarge),
))
],
),
Divider(
height: 5,
color: theme.textTheme.bodyLarge!.color,
),
bigPictureState.isCompactView() ? Container() : const SizedBox(height: 10),
bigPictureState.isCompactView()
? Container()
: Row(
Column(
children: [
if (!bigPictureState.isCompactView())
Container(
margin: EdgeInsets.symmetric(horizontal: 5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('${strategy!.tradingYears.ceil()}y${(strategy!.tradingYears % 1 * 12).ceil()}m'),
strategy!.startDate != null && strategy!.endDate != null
? Text(
'${DateFormat.yMd().format(strategy!.startDate!)} to ${DateFormat.yMd().format(strategy!.endDate!)}')
: Container()
_buildTickerTitle(titleWidth, theme, TextAlign.start),
SizedBox(
width: cardWidth / 2 - 30,
child: Align(
alignment: Alignment.centerRight,
child: Text(tickerDescription, style: theme.textTheme.bodyLarge),
),
),
],
),
bigPictureState.isCompactView() ? Container() : const SizedBox(height: 10)
]),
bigPictureState.isCompactView()
? Container()
: InkWell(
child: Container(
color: Colors.lightBlue.withOpacity(0),
padding: EdgeInsets.only(left: 40, right: 40, bottom: AppTheme.isDesktopWeb() ? 0 : 30),
child: const Icon(
Icons.add,
)),
onTap: () async {
final List<StockTicker>? tickers = await showSearch(context: context, delegate: tickerSearch);
await bigPictureState.joinTicker(ticker, tickers);
await bigPictureState.persistTickers();
},
),
if (bigPictureState.isCompactView()) _buildTickerTitle(titleWidth, theme, TextAlign.center),
if (bigPictureState.isCompactView()) priceVariationChip,
if (!bigPictureState.isCompactView())
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('\$${strategy.endPrice.toStringAsFixed(2)}'),
priceVariationChip,
],
),
Divider(height: 5, color: theme.textTheme.bodyLarge?.color),
if (!bigPictureState.isCompactView())
Column(
children: [
const SizedBox(height: 10),
_buildDateRow(),
const SizedBox(height: 10),
],
),
],
),
if (!bigPictureState.isCompactView()) _buildAddButton(bigPictureState, context),
],
);
}

/// Ticker symbol
Widget _buildTickerTitle(double width, ThemeData theme, TextAlign textAlign) => Center(
child: SizedBox(
width: width,
child: Text(
ticker.symbol,
style: theme.textTheme.titleLarge,
textAlign: textAlign,
),
),
);

/// Builds the row displaying the strategy duration.
///
/// Visible only in the expanded view mode.
Widget _buildDateRow() => Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('${strategy!.tradingYears.ceil()}y${(strategy!.tradingYears % 1 * 12).ceil()}m'),
if (strategy?.startDate != null && strategy?.endDate != null)
Text('${DateFormat.yMd().format(strategy!.startDate!)} to ${DateFormat.yMd().format(strategy!.endDate!)}'),
],
);

/// Builds the add button for adding more details to the strategy.
///
/// Visible only in the expanded view mode.
Widget _buildAddButton(BigPictureStateProvider bigPictureState, BuildContext context) => InkWell(
child: Container(
color: Colors.lightBlue.withOpacity(0),
padding: EdgeInsets.only(left: 40, right: 40, bottom: AppTheme.isDesktopWeb() ? 0 : 30),
child: const Icon(Icons.add),
),
onTap: () async {
final List<StockTicker>? tickers = await showSearch(
context: context, delegate: TickerSearch(searchFieldLabel: 'Add'.t, suggestions: HomeScreen.suggestions));
if (tickers != null) {
await bigPictureState.joinTicker(ticker, tickers);
await bigPictureState.persistTickers();
}
},
);
}
25 changes: 19 additions & 6 deletions lib/big_picture/ui/resume/strategy_resume_ui.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import 'dart:ui';

import 'package:app_dependencies/app_dependencies.dart';
import 'package:flutter/material.dart';
import 'package:pinch_zoom_release_unzoom/pinch_zoom_release_unzoom.dart';
import 'package:provider/provider.dart';
import 'package:stock_market_data/stock_market_data.dart';
import 'package:ticker_details/ticker_details.dart';
import 'package:turing_deal/big_picture/state/big_picture_state_provider.dart';
import 'package:turing_deal/big_picture/ui/resume/strategy_resume_details_ui.dart';
Expand Down Expand Up @@ -44,9 +42,18 @@ class StrategyResume extends StatelessWidget {
if (bigPictureState.isCompactView()) {
cardWidth /= 3;
cardWidth -= 5;
print('card width: $cardWidth');
}

final double variation = (strategy.endPrice / strategy.yesterdayPrice - 1) * 100;
final ColorScaleWidget colorScaleWidget = ColorScaleWidget(
value: variation,
minColor: Theme.of(context).colorScheme.error,
maxColor: Theme.of(context).colorScheme.primary,
minValue: -2.5,
maxValue: 2.5,
);
final Color color = colorScaleWidget.getColorForValue(variation);

// Main widget structure
return Dismissible(
key: GlobalKey(),
Expand Down Expand Up @@ -76,7 +83,7 @@ class StrategyResume extends StatelessWidget {
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Theme.of(context).colorScheme.primary,
color: color,
blurRadius: 2,
offset: const Offset(2, 2), // Adjust the offset to control the shadow direction
),
Expand All @@ -99,7 +106,13 @@ class StrategyResume extends StatelessWidget {
child: strategy.progress > 0
? Column(
children: [
StrategyResumeHeader(ticker, strategy, cardWidth),
StrategyResumeHeader(
ticker: ticker,
strategy: strategy,
cardWidth: cardWidth,
variation: variation,
color: color,
),
StrategyResumeDetails(strategy),
strategy.progress < 100 ? const CircularProgressIndicator() : Container()
],
Expand Down
Loading

0 comments on commit bb12646

Please sign in to comment.