253 lines
6.7 KiB
Dart
253 lines
6.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:mobile_monitoring/core/constants/colors.dart';
|
|
import 'package:mobile_monitoring/ui/shared/components/custom_button.dart';
|
|
|
|
/// Custom Dialog - Dialog yang reusable
|
|
class CustomDialog {
|
|
/// Confirmation Dialog - Dialog untuk konfirmasi aksi
|
|
static Future<bool?> showConfirmation({
|
|
required BuildContext context,
|
|
required String title,
|
|
required String message,
|
|
String confirmText = 'Ya',
|
|
String cancelText = 'Tidak',
|
|
bool isDangerous = false,
|
|
}) {
|
|
return showDialog<bool>(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: Text(title),
|
|
content: Text(message),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(false),
|
|
child: Text(cancelText),
|
|
),
|
|
CustomButton(
|
|
text: confirmText,
|
|
type: isDangerous ? ButtonType.danger : ButtonType.primary,
|
|
size: ButtonSize.small,
|
|
onPressed: () => Navigator.of(context).pop(true),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Info Dialog - Dialog untuk menampilkan informasi
|
|
static Future<void> showInfo({
|
|
required BuildContext context,
|
|
required String title,
|
|
required String message,
|
|
String buttonText = 'OK',
|
|
IconData? icon,
|
|
Color? iconColor,
|
|
}) {
|
|
return showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: Row(
|
|
children: [
|
|
if (icon != null) ...[
|
|
Icon(icon, color: iconColor ?? AppColors.info),
|
|
const SizedBox(width: 12),
|
|
],
|
|
Expanded(child: Text(title)),
|
|
],
|
|
),
|
|
content: Text(message),
|
|
actions: [
|
|
CustomButton(
|
|
text: buttonText,
|
|
type: ButtonType.primary,
|
|
size: ButtonSize.small,
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Error Dialog - Dialog untuk menampilkan error
|
|
static Future<void> showError({
|
|
required BuildContext context,
|
|
required String title,
|
|
required String message,
|
|
String buttonText = 'OK',
|
|
}) {
|
|
return showInfo(
|
|
context: context,
|
|
title: title,
|
|
message: message,
|
|
buttonText: buttonText,
|
|
icon: Icons.error_outline,
|
|
iconColor: AppColors.error,
|
|
);
|
|
}
|
|
|
|
/// Success Dialog - Dialog untuk menampilkan success
|
|
static Future<void> showSuccess({
|
|
required BuildContext context,
|
|
required String title,
|
|
required String message,
|
|
String buttonText = 'OK',
|
|
}) {
|
|
return showInfo(
|
|
context: context,
|
|
title: title,
|
|
message: message,
|
|
buttonText: buttonText,
|
|
icon: Icons.check_circle_outline,
|
|
iconColor: AppColors.success,
|
|
);
|
|
}
|
|
|
|
/// Loading Dialog - Dialog untuk menampilkan loading
|
|
static void showLoading(BuildContext context, {String? message}) {
|
|
showDialog(
|
|
context: context,
|
|
barrierDismissible: false,
|
|
builder: (context) => PopScope(
|
|
canPop: false,
|
|
child: AlertDialog(
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const CircularProgressIndicator(),
|
|
if (message != null) ...[
|
|
const SizedBox(height: 16),
|
|
Text(message),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Custom Content Dialog - Dialog dengan custom content
|
|
static Future<T?> showCustom<T>({
|
|
required BuildContext context,
|
|
required String title,
|
|
required Widget content,
|
|
List<Widget>? actions,
|
|
bool barrierDismissible = true,
|
|
}) {
|
|
return showDialog<T>(
|
|
context: context,
|
|
barrierDismissible: barrierDismissible,
|
|
builder: (context) => AlertDialog(
|
|
title: Text(title),
|
|
content: content,
|
|
actions: actions,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Bottom Sheet Dialog - Bottom sheet yang reusable
|
|
class CustomBottomSheet {
|
|
/// Show custom bottom sheet
|
|
static Future<T?> show<T>({
|
|
required BuildContext context,
|
|
required Widget child,
|
|
String? title,
|
|
bool isDismissible = true,
|
|
bool enableDrag = true,
|
|
double? height,
|
|
}) {
|
|
return showModalBottomSheet<T>(
|
|
context: context,
|
|
isDismissible: isDismissible,
|
|
enableDrag: enableDrag,
|
|
isScrollControlled: true,
|
|
backgroundColor: Colors.transparent,
|
|
builder: (context) => Container(
|
|
height: height,
|
|
decoration: const BoxDecoration(
|
|
color: AppColors.white,
|
|
borderRadius: BorderRadius.only(
|
|
topLeft: Radius.circular(20),
|
|
topRight: Radius.circular(20),
|
|
),
|
|
),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
if (enableDrag) ...[
|
|
const SizedBox(height: 8),
|
|
Container(
|
|
width: 40,
|
|
height: 4,
|
|
decoration: BoxDecoration(
|
|
color: AppColors.mediumGray,
|
|
borderRadius: BorderRadius.circular(2),
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
],
|
|
if (title != null) ...[
|
|
Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Text(
|
|
title,
|
|
style: const TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.w600,
|
|
color: AppColors.textPrimary,
|
|
),
|
|
),
|
|
),
|
|
const Divider(height: 1),
|
|
],
|
|
Flexible(child: child),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Show list bottom sheet
|
|
static Future<T?> showList<T>({
|
|
required BuildContext context,
|
|
required String title,
|
|
required List<BottomSheetItem<T>> items,
|
|
}) {
|
|
return show<T>(
|
|
context: context,
|
|
title: title,
|
|
child: ListView.builder(
|
|
shrinkWrap: true,
|
|
itemCount: items.length,
|
|
itemBuilder: (context, index) {
|
|
final item = items[index];
|
|
return ListTile(
|
|
leading: item.icon != null
|
|
? Icon(item.icon, color: item.iconColor)
|
|
: null,
|
|
title: Text(item.title),
|
|
subtitle: item.subtitle != null ? Text(item.subtitle!) : null,
|
|
onTap: () => Navigator.of(context).pop(item.value),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class BottomSheetItem<T> {
|
|
final String title;
|
|
final String? subtitle;
|
|
final IconData? icon;
|
|
final Color? iconColor;
|
|
final T value;
|
|
|
|
BottomSheetItem({
|
|
required this.title,
|
|
this.subtitle,
|
|
this.icon,
|
|
this.iconColor,
|
|
required this.value,
|
|
});
|
|
}
|