import 'dart:math'; import 'package:flutter/material.dart'; import 'package:tangocard_reader/models/data_entry.dart'; class Flashcard extends StatelessWidget { final YokutangoEntry? card; final int? cardIndex; final bool isLeftSide; final bool languageFlipped; final int amountOfCardsOnStack; final double rotationAmount; const Flashcard({ this.card, this.cardIndex, this.isLeftSide = false, this.languageFlipped = false, this.amountOfCardsOnStack = 10, this.rotationAmount = pi / 18, Key? key, }) : super(key: key); @override Widget build(BuildContext context) { final stackItems = []; final rng = Random(); for (int i = 0; i < amountOfCardsOnStack; i++) { stackItems.add( makeBlankCard( offset: (isLeftSide ? -1 : 1) * (amountOfCardsOnStack - i) * 2, rotationOrigin: isLeftSide ? 0.9 : 0.1, angle: rng.nextDouble() * rotationAmount - rotationAmount / 2, ), ); } Widget? content; if (card != null) { if (isLeftSide && !languageFlipped || !isLeftSide && languageFlipped) { content = _NorwegianContent(card: card!); } else { content = _JapaneseContent(card: card!); } } stackItems.add(_FlashCardPaper( child: content, cardIndex: cardIndex, )); return Center( child: SizedBox( width: MediaQuery.of(context).size.width / 2 - 60, child: Stack( children: stackItems, ), ), ); } Widget makeBlankCard({ required double offset, required double rotationOrigin, required double angle, }) => Transform.translate( offset: Offset( offset, 0, ), child: Transform.rotate( angle: angle, alignment: FractionalOffset( rotationOrigin, 0.5, ), child: const _FlashCardPaper()), ); } class _FlashCardPaper extends StatelessWidget { final Widget? child; final int? cardIndex; const _FlashCardPaper({ this.child, this.cardIndex, Key? key, }) : super(key: key); @override Widget build(BuildContext context) { Widget? content; if (child != null) { content = Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded(child: Container()), child!, Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( (cardIndex != null) ? (cardIndex! + 1).toString() : "?", style: const TextStyle(color: Colors.black), ) ], ), ), ], ); } return AspectRatio( aspectRatio: 5 / 2, child: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: Colors.white, border: Border.all(), ), child: content, ), ); } } class _NorwegianContent extends StatelessWidget { final YokutangoEntry card; const _NorwegianContent({ required this.card, Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return Expanded( child: FittedBox( fit: BoxFit.fitHeight, child: DefaultTextStyle.merge( style: const TextStyle( fontFamily: 'Heart Warming', color: Colors.black, ), child: Column( children: card.norwegian.map((n) { final text = (n.hints == null) ? n.word : "${n.word} (${n.hints?.join(', ')})"; return Text( text, style: const TextStyle(color: Colors.black), ); }).toList(), ), ), ), ); } } class _JapaneseContent extends StatelessWidget { final YokutangoEntry card; const _JapaneseContent({ required this.card, Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return Expanded( flex: 3, child: FittedBox( fit: BoxFit.fitHeight, child: DefaultTextStyle.merge( style: const TextStyle( fontFamily: 'K Gothic', color: Colors.black, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: card.japanese .map((e) => Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(e.word), const Divider(), Text(e.romaji ?? ""), ])) .toList(), ), ), ), ); } }