feat(recipes): add recipe visibility and sharing features
- Implemented functionality to set recipe visibility (public/private) with appropriate checks for user permissions. - Added ability to share recipes with other users, including validation for existing users and permissions. - Introduced new DTOs for setting visibility and sharing recipes. - Updated RecipesController and RecipesService to handle new endpoints for visibility and sharing. - Enhanced inventory preview to consider user permissions and shared recipes. - Updated front-end to support new sharing and visibility features, including UI changes for recipe detail and admin user management.
This commit is contained in:
@@ -3,7 +3,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../../core/api/api_error_mapper.dart';
|
||||
import '../../../core/utils/global_error_handler.dart';
|
||||
import '../../auth/data/auth_providers.dart';
|
||||
import '../data/import_providers.dart';
|
||||
@@ -23,17 +22,17 @@ class RecipeImportTab extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _RecipeImportTabState extends ConsumerState<RecipeImportTab> {
|
||||
// Shared state
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
|
||||
// File mode
|
||||
PlatformFile? _pickedFile;
|
||||
|
||||
// URL mode
|
||||
_Method _method = _Method.file;
|
||||
final _urlCtrl = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_urlCtrl.addListener(() => setState(() {}));
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_urlCtrl.dispose();
|
||||
@@ -59,17 +58,15 @@ class _RecipeImportTabState extends ConsumerState<RecipeImportTab> {
|
||||
|
||||
Future<void> _submit() async {
|
||||
if (_pickedFile == null && _method == _Method.file) {
|
||||
setState(() => _error = 'Vänligen välj en fil först');
|
||||
showGlobalErrorDialog(context, 'Vänligen välj en fil först');
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
});
|
||||
setState(() => _isLoading = true);
|
||||
|
||||
try {
|
||||
final token = await ref.read(authStateProvider.future);
|
||||
final token = ref.read(authStateProvider).valueOrNull ??
|
||||
await ref.read(authStateProvider.future);
|
||||
final repo = ref.read(importRepositoryProvider);
|
||||
final result = _method == _Method.file
|
||||
? await repo.importFile(
|
||||
@@ -83,7 +80,10 @@ class _RecipeImportTabState extends ConsumerState<RecipeImportTab> {
|
||||
);
|
||||
|
||||
if (!mounted) return;
|
||||
context.push('/recipes/create', extra: result);
|
||||
context.push('/recipes/create', extra: {
|
||||
'markdown': result.markdown,
|
||||
'imageUrl': result.imageUrl,
|
||||
});
|
||||
} catch (e) {
|
||||
showGlobalErrorDialog(context, 'Ett fel uppstod vid import: $e');
|
||||
} finally {
|
||||
@@ -172,7 +172,6 @@ class _RecipeImportTabState extends ConsumerState<RecipeImportTab> {
|
||||
prefixIcon: Icon(Icons.link),
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (_) => setState(() {}),
|
||||
onSubmitted: (_) {
|
||||
if (_canSubmit) _submit();
|
||||
},
|
||||
@@ -193,31 +192,6 @@ class _RecipeImportTabState extends ConsumerState<RecipeImportTab> {
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
|
||||
// ── Felmeddelande ───────────────────────────────────────────────
|
||||
if (_error != null) ...[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.errorContainer,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.error_outline,
|
||||
color: theme.colorScheme.onErrorContainer, size: 18),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
_error!,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onErrorContainer),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
|
||||
// ── Knapp ───────────────────────────────────────────────────────
|
||||
FilledButton.icon(
|
||||
|
||||
Reference in New Issue
Block a user