feat(app): add manual entry and sharing flows
This commit is contained in:
@@ -26,7 +26,7 @@ class CategorySelector extends ConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final categoriesAsync = ref.watch(categoriesProvider);
|
||||
|
||||
|
||||
return categoriesAsync.when(
|
||||
data: (categories) {
|
||||
return SizedBox(
|
||||
@@ -39,7 +39,9 @@ class CategorySelector extends ConsumerWidget {
|
||||
context: context,
|
||||
label: '전체',
|
||||
icon: Icons.restaurant_menu,
|
||||
color: isDark ? AppColors.darkPrimary : AppColors.lightPrimary,
|
||||
color: isDark
|
||||
? AppColors.darkPrimary
|
||||
: AppColors.lightPrimary,
|
||||
isSelected: selectedCategory == null,
|
||||
onTap: () => onCategorySelected(null),
|
||||
),
|
||||
@@ -49,7 +51,7 @@ class CategorySelector extends ConsumerWidget {
|
||||
final isSelected = multiSelect
|
||||
? selectedCategories?.contains(category) ?? false
|
||||
: selectedCategory == category;
|
||||
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: _buildCategoryChip(
|
||||
@@ -74,30 +76,26 @@ class CategorySelector extends ConsumerWidget {
|
||||
},
|
||||
loading: () => const SizedBox(
|
||||
height: 50,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
error: (error, stack) => const SizedBox(
|
||||
height: 50,
|
||||
child: Center(
|
||||
child: Text('카테고리를 불러올 수 없습니다'),
|
||||
),
|
||||
child: Center(child: Text('카테고리를 불러올 수 없습니다')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _handleMultiSelect(String category) {
|
||||
if (onMultipleSelected == null || selectedCategories == null) return;
|
||||
|
||||
|
||||
final List<String> updatedCategories = List.from(selectedCategories!);
|
||||
|
||||
|
||||
if (updatedCategories.contains(category)) {
|
||||
updatedCategories.remove(category);
|
||||
} else {
|
||||
updatedCategories.add(category);
|
||||
}
|
||||
|
||||
|
||||
onMultipleSelected!(updatedCategories);
|
||||
}
|
||||
|
||||
@@ -110,7 +108,7 @@ class CategorySelector extends ConsumerWidget {
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
@@ -120,11 +118,11 @@ class CategorySelector extends ConsumerWidget {
|
||||
duration: const Duration(milliseconds: 200),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
color: isSelected
|
||||
? color.withOpacity(0.2)
|
||||
: isDark
|
||||
? AppColors.darkSurface
|
||||
: AppColors.lightBackground,
|
||||
: isDark
|
||||
? AppColors.darkSurface
|
||||
: AppColors.lightBackground,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(
|
||||
color: isSelected ? color : Colors.transparent,
|
||||
@@ -137,21 +135,21 @@ class CategorySelector extends ConsumerWidget {
|
||||
Icon(
|
||||
icon,
|
||||
size: 20,
|
||||
color: isSelected
|
||||
? color
|
||||
: isDark
|
||||
? AppColors.darkTextSecondary
|
||||
: AppColors.lightTextSecondary,
|
||||
color: isSelected
|
||||
? color
|
||||
: isDark
|
||||
? AppColors.darkTextSecondary
|
||||
: AppColors.lightTextSecondary,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: isSelected
|
||||
? color
|
||||
: isDark
|
||||
? AppColors.darkText
|
||||
: AppColors.lightText,
|
||||
color: isSelected
|
||||
? color
|
||||
: isDark
|
||||
? AppColors.darkText
|
||||
: AppColors.lightText,
|
||||
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
||||
),
|
||||
),
|
||||
@@ -180,7 +178,7 @@ class CategorySelectionDialog extends ConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
final categoriesAsync = ref.watch(categoriesProvider);
|
||||
|
||||
|
||||
return AlertDialog(
|
||||
backgroundColor: isDark ? AppColors.darkSurface : AppColors.lightSurface,
|
||||
title: Column(
|
||||
@@ -193,7 +191,9 @@ class CategorySelectionDialog extends ConsumerWidget {
|
||||
subtitle!,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: isDark ? AppColors.darkTextSecondary : AppColors.lightTextSecondary,
|
||||
color: isDark
|
||||
? AppColors.darkTextSecondary
|
||||
: AppColors.lightTextSecondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -214,12 +214,14 @@ class CategorySelectionDialog extends ConsumerWidget {
|
||||
itemBuilder: (context, index) {
|
||||
final category = categories[index];
|
||||
final isSelected = selectedCategories.contains(category);
|
||||
|
||||
|
||||
return _CategoryGridItem(
|
||||
category: category,
|
||||
isSelected: isSelected,
|
||||
onTap: () {
|
||||
final updatedCategories = List<String>.from(selectedCategories);
|
||||
final updatedCategories = List<String>.from(
|
||||
selectedCategories,
|
||||
);
|
||||
if (isSelected) {
|
||||
updatedCategories.remove(category);
|
||||
} else {
|
||||
@@ -231,12 +233,9 @@ class CategorySelectionDialog extends ConsumerWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
loading: () => const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
error: (error, stack) => Center(
|
||||
child: Text('카테고리를 불러올 수 없습니다: $error'),
|
||||
),
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, stack) =>
|
||||
Center(child: Text('카테고리를 불러올 수 없습니다: $error')),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
@@ -244,7 +243,9 @@ class CategorySelectionDialog extends ConsumerWidget {
|
||||
child: Text(
|
||||
'취소',
|
||||
style: TextStyle(
|
||||
color: isDark ? AppColors.darkTextSecondary : AppColors.lightTextSecondary,
|
||||
color: isDark
|
||||
? AppColors.darkTextSecondary
|
||||
: AppColors.lightTextSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -274,7 +275,7 @@ class _CategoryGridItem extends StatelessWidget {
|
||||
final color = CategoryMapper.getColor(category);
|
||||
final icon = CategoryMapper.getIcon(category);
|
||||
final displayName = CategoryMapper.getDisplayName(category);
|
||||
|
||||
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
@@ -284,11 +285,11 @@ class _CategoryGridItem extends StatelessWidget {
|
||||
duration: const Duration(milliseconds: 200),
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
color: isSelected
|
||||
? color.withOpacity(0.2)
|
||||
: isDark
|
||||
? AppColors.darkCard
|
||||
: AppColors.lightCard,
|
||||
: isDark
|
||||
? AppColors.darkCard
|
||||
: AppColors.lightCard,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: isSelected ? color : Colors.transparent,
|
||||
@@ -301,22 +302,22 @@ class _CategoryGridItem extends StatelessWidget {
|
||||
Icon(
|
||||
icon,
|
||||
size: 28,
|
||||
color: isSelected
|
||||
? color
|
||||
: isDark
|
||||
? AppColors.darkTextSecondary
|
||||
: AppColors.lightTextSecondary,
|
||||
color: isSelected
|
||||
? color
|
||||
: isDark
|
||||
? AppColors.darkTextSecondary
|
||||
: AppColors.lightTextSecondary,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
displayName,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: isSelected
|
||||
? color
|
||||
: isDark
|
||||
? AppColors.darkText
|
||||
: AppColors.lightText,
|
||||
color: isSelected
|
||||
? color
|
||||
: isDark
|
||||
? AppColors.darkText
|
||||
: AppColors.lightText,
|
||||
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
@@ -329,4 +330,4 @@ class _CategoryGridItem extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user