billing_questions_widget.dart 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import 'dart:convert';
  2. import 'package:expansion_tile_card/expansion_tile_card.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:photos/core/network/network.dart';
  5. import 'package:photos/ente_theme_data.dart';
  6. import 'package:photos/ui/common/loading_widget.dart';
  7. class BillingQuestionsWidget extends StatelessWidget {
  8. const BillingQuestionsWidget({
  9. Key? key,
  10. }) : super(key: key);
  11. @override
  12. Widget build(BuildContext context) {
  13. return FutureBuilder(
  14. future: NetworkClient.instance
  15. .getDio()
  16. .get("https://static.ente.io/faq.json")
  17. .then((response) {
  18. final faqItems = <FaqItem>[];
  19. for (final item in response.data as List) {
  20. faqItems.add(FaqItem.fromMap(item));
  21. }
  22. return faqItems;
  23. }),
  24. builder: (BuildContext context, AsyncSnapshot snapshot) {
  25. if (snapshot.hasData) {
  26. final faqs = <Widget>[];
  27. faqs.add(
  28. const Padding(
  29. padding: EdgeInsets.all(24),
  30. child: Text(
  31. "FAQs",
  32. style: TextStyle(
  33. fontSize: 18,
  34. fontWeight: FontWeight.bold,
  35. ),
  36. ),
  37. ),
  38. );
  39. for (final faq in snapshot.data) {
  40. faqs.add(FaqWidget(faq: faq));
  41. }
  42. faqs.add(
  43. const Padding(
  44. padding: EdgeInsets.all(16),
  45. ),
  46. );
  47. return SingleChildScrollView(
  48. child: Column(
  49. children: faqs,
  50. ),
  51. );
  52. } else {
  53. return const EnteLoadingWidget();
  54. }
  55. },
  56. );
  57. }
  58. }
  59. class FaqWidget extends StatelessWidget {
  60. const FaqWidget({
  61. Key? key,
  62. required this.faq,
  63. }) : super(key: key);
  64. final FaqItem? faq;
  65. @override
  66. Widget build(BuildContext context) {
  67. return Padding(
  68. padding: const EdgeInsets.all(2),
  69. child: ExpansionTileCard(
  70. elevation: 0,
  71. title: Text(faq!.q!),
  72. expandedTextColor: Theme.of(context).colorScheme.greenAlternative,
  73. baseColor: Theme.of(context).cardColor,
  74. children: [
  75. Padding(
  76. padding: const EdgeInsets.only(
  77. left: 16,
  78. right: 16,
  79. bottom: 12,
  80. ),
  81. child: Text(
  82. faq!.a!,
  83. style: const TextStyle(
  84. height: 1.5,
  85. ),
  86. ),
  87. )
  88. ],
  89. ),
  90. );
  91. }
  92. }
  93. class FaqItem {
  94. final String? q;
  95. final String? a;
  96. FaqItem({
  97. this.q,
  98. this.a,
  99. });
  100. FaqItem copyWith({
  101. String? q,
  102. String? a,
  103. }) {
  104. return FaqItem(
  105. q: q ?? this.q,
  106. a: a ?? this.a,
  107. );
  108. }
  109. Map<String, dynamic> toMap() {
  110. return {
  111. 'q': q,
  112. 'a': a,
  113. };
  114. }
  115. factory FaqItem.fromMap(Map<String, dynamic> map) {
  116. return FaqItem(
  117. q: map['q'] ?? 'q',
  118. a: map['a'] ?? 'a',
  119. );
  120. }
  121. String toJson() => json.encode(toMap());
  122. factory FaqItem.fromJson(String source) =>
  123. FaqItem.fromMap(json.decode(source));
  124. @override
  125. String toString() => 'FaqItem(q: $q, a: $a)';
  126. @override
  127. bool operator ==(Object o) {
  128. if (identical(this, o)) return true;
  129. return o is FaqItem && o.q == q && o.a == a;
  130. }
  131. @override
  132. int get hashCode => q.hashCode ^ a.hashCode;
  133. }