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:
Nils-Johan Gynther
2026-05-02 09:19:59 +02:00
parent f67bf8baef
commit 41ae7d4d06
17 changed files with 742 additions and 124 deletions
@@ -81,6 +81,26 @@ class _AdminUsersPanelState extends ConsumerState<AdminUsersPanel> {
}
}
Future<void> _toggleRecipeSharing(UserAdmin user) async {
final newValue = !user.canShareRecipes;
final confirmed = await _confirm(
context,
newValue ? 'Tillåt receptdelning' : 'Blockera receptdelning',
'${newValue ? 'Tillåt' : 'Blockera'} receptdelning för ${user.username}?',
);
if (!confirmed || !mounted) return;
try {
await ref
.read(adminRepositoryProvider)
.setRecipeSharing(user.id, canShareRecipes: newValue);
if (!mounted) return;
_load();
} catch (e) {
if (!mounted) return;
_showError(e);
}
}
Future<void> _resetPassword(UserAdmin user) async {
final confirmed = await _confirm(
context,
@@ -319,6 +339,7 @@ class _AdminUsersPanelState extends ConsumerState<AdminUsersPanel> {
user: _users[i],
onChangeRole: () => _changeRole(_users[i]),
onTogglePremium: () => _togglePremium(_users[i]),
onToggleRecipeSharing: () => _toggleRecipeSharing(_users[i]),
onEditEmail: () => _editEmail(_users[i]),
onResetPassword: () => _resetPassword(_users[i]),
onDelete: () => _deleteUser(_users[i]),
@@ -364,6 +385,7 @@ class _UserTile extends StatelessWidget {
final UserAdmin user;
final VoidCallback onChangeRole;
final VoidCallback onTogglePremium;
final VoidCallback onToggleRecipeSharing;
final VoidCallback onEditEmail;
final VoidCallback onResetPassword;
final VoidCallback onDelete;
@@ -372,6 +394,7 @@ class _UserTile extends StatelessWidget {
required this.user,
required this.onChangeRole,
required this.onTogglePremium,
required this.onToggleRecipeSharing,
required this.onEditEmail,
required this.onResetPassword,
required this.onDelete,
@@ -418,6 +441,16 @@ class _UserTile extends StatelessWidget {
backgroundColor: theme.colorScheme.tertiaryContainer,
),
],
const SizedBox(width: 4),
Chip(
label: Text(user.canShareRecipes ? 'Delning: På' : 'Delning: Av'),
padding: EdgeInsets.zero,
visualDensity: VisualDensity.compact,
labelStyle: theme.textTheme.labelSmall,
backgroundColor: user.canShareRecipes
? theme.colorScheme.secondaryContainer
: theme.colorScheme.errorContainer,
),
],
),
],
@@ -432,6 +465,9 @@ class _UserTile extends StatelessWidget {
case 'premium':
onTogglePremium();
break;
case 'sharing':
onToggleRecipeSharing();
break;
case 'email':
onEditEmail();
break;
@@ -454,6 +490,14 @@ class _UserTile extends StatelessWidget {
value: 'premium',
child: Text(user.isPremium ? 'Ta bort Premium' : 'Ge Premium'),
),
PopupMenuItem(
value: 'sharing',
child: Text(
user.canShareRecipes
? 'Blockera receptdelning'
: 'Tillåt receptdelning',
),
),
const PopupMenuItem(
value: 'email',
child: Text('Ändra e-post'),