common_dialog_view.dart 5.75 KB
import 'dart:math' as math;

import 'package:doublefeel_flutter/app/actions/dialog_action.dart';
import 'package:doublefeel_flutter/app/models/action_result.dart';
import 'package:doublefeel_flutter/app/models/dialog_meta_data.dart';
import 'package:doublefeel_flutter/core/theme/app_colors.dart';
import 'package:doublefeel_flutter/core/util/size_extensions.dart';
import 'package:doublefeel_flutter/r.dart';
import 'package:flutter/material.dart';

class CommonDialogView extends StatelessWidget {
  const CommonDialogView({
    super.key,
    required this.dialogMetaData,
    this.onAction,
  });

  final DialogMetaData dialogMetaData;
  final ValueChanged<ActionResult<DialogAction, DialogMetaData>>? onAction;

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.sizeOf(context).width;
    final dialogWidth = math.min(300.dp, screenWidth - 48.dp);
    final iconAsset = dialogMetaData.iconAsset;

    return Center(
      child: Material(
        color: Colors.transparent,
        child: Container(
          width: dialogWidth,
          padding: EdgeInsets.fromLTRB(24.dp, 28.dp, 24.dp, 20.dp),
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(24.dp),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              if (iconAsset != null && iconAsset.isNotEmpty) ...[
                Image.asset(
                  iconAsset,
                  width: 56.dp,
                  height: 56.dp,
                  fit: BoxFit.contain,
                ),
                SizedBox(height: 18.h),
              ],
              if (dialogMetaData.title.isNotEmpty) ...[
                Text(
                  dialogMetaData.title,
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                  textAlign: TextAlign.center,
                  style: const TextStyle(
                    color: AppColors.textPrimary,
                    fontSize: 18,
                    fontWeight: FontWeight.w600,
                    height: 1.28,
                  ),
                ),
                SizedBox(height: 12.h),
              ],
              if (dialogMetaData.message.isNotEmpty)
                ConstrainedBox(
                  constraints: BoxConstraints(maxHeight: 150.h),
                  child: SingleChildScrollView(
                    physics: const BouncingScrollPhysics(),
                    child: Text(
                      dialogMetaData.message,
                      textAlign: TextAlign.center,
                      style: const TextStyle(
                        color: AppColors.textSecondary,
                        fontSize: 15,
                        fontWeight: FontWeight.w400,
                        height: 1.35,
                      ),
                    ),
                  ),
                ),
              SizedBox(height: 24.h),
              _DialogButton(
                text: dialogMetaData.confirmText,
                textColor: Colors.white,
                backgroundColor: AppColors.primary,
                fontWeight: FontWeight.w600,
                showProBadge: dialogMetaData.showConfirmPro,
                onTap: () {
                  onAction?.call(
                    ActionResult(
                      action: DialogAction.confirm,
                      data: dialogMetaData,
                    ),
                  );
                },
              ),
              if (dialogMetaData.cancelText.isNotEmpty) ...[
                SizedBox(height: 4.h),
                _DialogButton(
                  text: dialogMetaData.cancelText,
                  textColor: AppColors.textSecondary,
                  fontWeight: FontWeight.w400,
                  onTap: () {
                    onAction?.call(
                      ActionResult(
                        action: DialogAction.cancel,
                        data: dialogMetaData,
                      ),
                    );
                  },
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}

class _DialogButton extends StatelessWidget {
  const _DialogButton({
    required this.text,
    required this.textColor,
    required this.fontWeight,
    required this.onTap,
    this.backgroundColor,
    this.showProBadge = false,
  });

  final String text;
  final Color textColor;
  final FontWeight fontWeight;
  final VoidCallback onTap;
  final Color? backgroundColor;
  final bool showProBadge;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      behavior: HitTestBehavior.opaque,
      child: Stack(
        clipBehavior: Clip.none,
        children: [
          Container(
            width: 220.dp,
            height: 48.h,
            margin: EdgeInsets.only(top: showProBadge ? 5.h : 0),
            alignment: Alignment.center,
            decoration: BoxDecoration(
              color: backgroundColor,
              borderRadius: BorderRadius.circular(24.dp),
            ),
            padding: EdgeInsets.symmetric(horizontal: 16.dp),
            child: Text(
              text,
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
              textAlign: TextAlign.center,
              style: TextStyle(
                color: textColor,
                fontSize: 14,
                fontWeight: fontWeight,
                height: 1.2,
              ),
            ),
          ),
          if (showProBadge)
            Positioned(
              top: 0,
              right: 0,
              child: Image.asset(
                R.assetsImagesProIcon,
                width: 32.dp,
                height: 12.h,
                fit: BoxFit.contain,
              ),
            ),
        ],
      ),
    );
  }
}