Commit a280cbb9 authored by Tuan Anh Nguyen's avatar Tuan Anh Nguyen
Browse files

feat: add back page for postcard creation

parent cfc29f4c
Loading
Loading
Loading
Loading
+170 −77
Original line number Diff line number Diff line
import 'package:country_picker/country_picker.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:stamped/bottom_nav_bar/widget/bottom_nav_bar.dart';
import 'package:stamped/common/service/ioc_container.dart';
import 'package:stamped/common/util/shared_ui_constants.dart';
import 'package:stamped/common/widget/future_builder_handler.dart';
import 'package:stamped/common/widget/page_template.dart';
import 'package:stamped/pages/create/notifiers/create_postcard_notifier.dart';
import 'package:stamped/service/auth_service.dart';
@@ -38,24 +41,9 @@ class _CreateBackPageState extends State<CreateBackPage> {
    return PageTemplate(
      title: 'Create a Postcard',
      actions: [
        IconButton(
          onPressed: () {
            createPostcardNotifier.text = _textEditingController.text;
            // TODO: select destination country
          },
          icon: Icon(Icons.navigate_next),
        ),
        _buildSubmitButton(createPostcardNotifier, context),
      ],
      child: Container(
        decoration: BoxDecoration(
          color: Colors.white,
          border: Border.all(
            color: Colors.grey,
            width: 2,
          ),
        ),
        padding: EdgeInsets.all(STANDARD_GAP),
        height: double.infinity,
      child: _buildPostcardBackground(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
@@ -65,8 +53,24 @@ class _CreateBackPageState extends State<CreateBackPage> {
              color: Colors.black87,
            ),
            Spacer(),
            _buildGreetingsText(),
            _buildLocationText(createPostcardNotifier),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                _buildFadedText('Greetings from'),
                _buildFadedText('To:')
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                // _buildBoldText(createPostcardNotifier),
                FutureBuilderHandler(
                  future: createPostcardNotifier.location,
                  builder: (context, data) => _buildBoldText(data),
                ),
                _buildDestinationSelector(context, createPostcardNotifier),
              ],
            ),
            Spacer(),
            _buildFooter(
              createPostcardNotifier,
@@ -79,47 +83,139 @@ class _CreateBackPageState extends State<CreateBackPage> {
    );
  }

  Widget _buildTextField() {
    return TextField(
  IconButton _buildSubmitButton(
    CreatePostcardNotifier createPostcardNotifier,
    BuildContext context,
  ) =>
      IconButton(
        onPressed: () {
          if (_textEditingController.text == '') {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text(
                  'Please enter a message.',
                ),
              ),
            );

            return;
          }

          if (createPostcardNotifier.destination == null) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text(
                  'Please select a destination country.',
                ),
              ),
            );

            return;
          }

          createPostcardNotifier.text = _textEditingController.text;

          try {
            createPostcardNotifier.createPostcard();
          } on Exception catch (e) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(
                content: Text(
                  e.toString(),
                ),
              ),
            );
          }

          Navigator.pushReplacement(
            context,
            MaterialPageRoute(
              builder: (context) => BottomNavBar(),
            ),
          );
        },
        icon: Icon(Icons.check),
      );

  Widget _buildPostcardBackground({required Widget child}) => Container(
        decoration: BoxDecoration(
          color: Colors.white,
          border: Border.all(
            color: Colors.grey,
            width: 2,
          ),
        ),
        padding: EdgeInsets.all(STANDARD_GAP),
        height: double.infinity,
        child: child,
      );

  Widget _buildDestinationSelector(
    BuildContext context,
    CreatePostcardNotifier createPostcardNotifier,
  ) {
    final isNull = createPostcardNotifier.destination == null;

    return InkWell(
      onTap: () {
        showCountryPicker(
          context: context,
          onSelect: (Country country) {
            createPostcardNotifier.destination = country;
          },
        );
      },
      child: isNull
          ? Icon(
              Icons.cancel_presentation_sharp,
              color: Colors.black45,
            )
          : Text(
              createPostcardNotifier.destination?.flagEmoji ??
                  'Select a destination',
              style: TextStyle(
                fontSize: FONT_SIZE,
              ),
            ),
    );
  }

  Widget _buildTextField() => TextField(
        maxLength: 220,
        maxLines: 12,
        style: TextStyle(
          fontSize: FONT_SIZE,
        ),
        decoration: InputDecoration(
          hintText: 'Type a message',
          border: InputBorder.none,
        ),
        controller: _textEditingController,
      );
  }

  Widget _buildGreetingsText() {
    return Text(
      'Greetings from',
  Widget _buildFadedText(String text) => Text(
        text,
        style: TextStyle(
          color: Colors.grey,
          fontSize: FONT_SIZE,
          fontWeight: FontWeight.w600,
        ),
      );
  }

  Widget _buildLocationText(CreatePostcardNotifier notifier) {
    return Text(
      notifier.location,
  Widget _buildBoldText(String text) => Text(
        text,
        style: TextStyle(
          color: Colors.black,
          fontSize: FONT_SIZE,
          fontWeight: FontWeight.w800,
        ),
      );
  }

  Widget _buildFooter(
    CreatePostcardNotifier notifier,
    AuthService authService,
  ) {
    return Row(
  ) =>
      Row(
        mainAxisAlignment: MainAxisAlignment.start,
        mainAxisSize: MainAxisSize.max,
        children: [
@@ -136,10 +232,8 @@ class _CreateBackPageState extends State<CreateBackPage> {
          _buildSignature(authService),
        ],
      );
  }

  Widget _buildSignature(AuthService authService) {
    return Expanded(
  Widget _buildSignature(AuthService authService) => Expanded(
        child: Text(
          textAlign: TextAlign.right,
          authService.currentUser.userName,
@@ -150,4 +244,3 @@ class _CreateBackPageState extends State<CreateBackPage> {
        ),
      );
}
}
+62 −14
Original line number Diff line number Diff line
import 'dart:io';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:country_picker/country_picker.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:stamped/common/service/ioc_container.dart';
import 'package:stamped/data/entities/postcard_entity.dart';
import 'package:stamped/data/enums/image_type.dart';
import 'package:stamped/service/auth_service.dart';
import 'package:stamped/service/media_service.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:stamped/service/postcard_service.dart';
import 'package:stamped/service/user_service.dart';

class CreatePostcardNotifier extends ChangeNotifier {
  final _mediaService = get<MediaService>();
  final _userService = get<UserService>();
  final _postcardService = get<PostcardService>();
  final _authService = get<AuthService>();

  File? _postcardImage;
  String _postcardImageDownloadUrl = '';
  String text = '';

  final _mediaService = get<MediaService>();
  Country? _destination;

  File? get selectedImage => _postcardImage;
  String get postcardImageUrl => _postcardImageDownloadUrl;
  String get location => 'Germany'; // TODO
  String get stampUrl =>
      'https://firebasestorage.googleapis.com/v0/b/stamped-56619.appspot.com/o/stamps%2Fczech%20republic%2FPampeliska.jpg?alt=media&token=1e100348-e8cb-4361-b1e3-37b5037491f8';
  Future<String> get location async =>
      await _userService.getCurrentDeviceLocation();
  Country? get destination => _destination;

  set destination(Country? destination) {
    _destination = destination;
    notifyListeners();
  }

  Future<void> pickImage(ImageSource source) async {
    final pickedFile = await ImagePicker().pickImage(source: source);
@@ -57,16 +71,50 @@ class CreatePostcardNotifier extends ChangeNotifier {
  }

  Future<void> uploadPostcardImage() async {
    try {
      final imageRef = await _mediaService.uploadImage(
        _postcardImage!,
        imageType: ImageType.postcard,
      );

    if (imageRef == null) {
      _postcardImageDownloadUrl = '';
      return;
      _postcardImageDownloadUrl = await imageRef!.getDownloadURL();
    } on FirebaseException catch (_) {
      rethrow;
    }
  }

  Future<void> createPostcard() async {
    await uploadPostcardImage();

    _postcardImageDownloadUrl = await imageRef.getDownloadURL();
    final allCountryStamps = await _mediaService.getStampUrls(
      await location.then(
        (value) => value.toLowerCase(),
      ),
    );
    allCountryStamps.shuffle();
    final stampUrl = await allCountryStamps.first;

    _postcardService.create(
      PostcardEntity(
        id: '0',
        imagePath: _postcardImageDownloadUrl,
        stampPath: stampUrl,
        originLocation: await location,
        destinationLocation: _destination!.name,
        text: text,
        senderId:
            await _authService.userStream.first.then((value) => value!.uid),
        timestamp: Timestamp.now(),
      ),
    );

    _clear();
  }

  void _clear() {
    _postcardImage = null;
    _postcardImageDownloadUrl = '';
    text = '';
    _destination = null;
  }
}