Refactor code for improved readability and consistency in multiple files
This commit is contained in:
@@ -18,7 +18,9 @@ class PermissionBloc extends Bloc<PermissionEvent, PermissionState> {
|
||||
) async {
|
||||
emit(PermissionLoading());
|
||||
try {
|
||||
final response = await apiClient.getRaw('/orgs/${event.orgId}/permissions');
|
||||
final response = await apiClient.getRaw(
|
||||
'/orgs/${event.orgId}/permissions',
|
||||
);
|
||||
final capabilities = Capabilities(
|
||||
canRead: response['canRead'] ?? false,
|
||||
canWrite: response['canWrite'] ?? false,
|
||||
|
||||
@@ -56,7 +56,9 @@ class Invitation {
|
||||
role: json['role'],
|
||||
createdAt: DateTime.parse(json['createdAt']),
|
||||
expiresAt: DateTime.parse(json['expiresAt']),
|
||||
acceptedAt: json['acceptedAt'] != null ? DateTime.parse(json['acceptedAt']) : null,
|
||||
acceptedAt: json['acceptedAt'] != null
|
||||
? DateTime.parse(json['acceptedAt'])
|
||||
: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,13 +370,20 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNavButton(String label, IconData icon, {bool isAvatar = false, VoidCallback? onTap}) {
|
||||
Widget _buildNavButton(
|
||||
String label,
|
||||
IconData icon, {
|
||||
bool isAvatar = false,
|
||||
VoidCallback? onTap,
|
||||
}) {
|
||||
final isSelected = _selectedTab == label;
|
||||
final highlightColor = const Color.fromARGB(255, 100, 200, 255);
|
||||
final defaultColor = AppTheme.secondaryText;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onTap ?? () {
|
||||
onTap:
|
||||
onTap ??
|
||||
() {
|
||||
setState(() {
|
||||
_selectedTab = label;
|
||||
});
|
||||
@@ -495,7 +502,12 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
|
||||
const SizedBox(width: 16),
|
||||
_buildNavButton('Add', Icons.add),
|
||||
const SizedBox(width: 16),
|
||||
_buildNavButton('Settings', Icons.settings, onTap: () => _showOrganizationSettings(context)),
|
||||
_buildNavButton(
|
||||
'Settings',
|
||||
Icons.settings,
|
||||
onTap: () =>
|
||||
_showOrganizationSettings(context),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
_buildNavButton(
|
||||
'Profile',
|
||||
|
||||
@@ -71,7 +71,10 @@ class ApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getRaw(String path, {Map<String, dynamic>? queryParameters}) async {
|
||||
Future<Map<String, dynamic>> getRaw(
|
||||
String path, {
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _dio.get(path, queryParameters: queryParameters);
|
||||
return response.data;
|
||||
|
||||
@@ -39,7 +39,11 @@ class OrgApi {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> updateMemberRole(String orgId, String userId, String role) async {
|
||||
Future<void> updateMemberRole(
|
||||
String orgId,
|
||||
String userId,
|
||||
String role,
|
||||
) async {
|
||||
await _apiClient.patch(
|
||||
'/orgs/$orgId/members/$userId',
|
||||
data: {'role': role},
|
||||
@@ -58,7 +62,11 @@ class OrgApi {
|
||||
);
|
||||
}
|
||||
|
||||
Future<Invitation> createInvitation(String orgId, String username, String role) async {
|
||||
Future<Invitation> createInvitation(
|
||||
String orgId,
|
||||
String username,
|
||||
String role,
|
||||
) async {
|
||||
final result = await _apiClient.post(
|
||||
'/orgs/$orgId/invitations',
|
||||
data: {'username': username, 'role': role},
|
||||
@@ -78,7 +86,10 @@ class OrgApi {
|
||||
await _apiClient.delete('/orgs/$orgId/invitations/$invitationId');
|
||||
}
|
||||
|
||||
Future<JoinRequest> createJoinRequest(String orgId, {String? inviteToken}) async {
|
||||
Future<JoinRequest> createJoinRequest(
|
||||
String orgId, {
|
||||
String? inviteToken,
|
||||
}) async {
|
||||
final data = {'orgId': orgId};
|
||||
if (inviteToken != null) {
|
||||
data['inviteToken'] = inviteToken;
|
||||
@@ -98,7 +109,11 @@ class OrgApi {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> acceptJoinRequest(String orgId, String requestId, String role) async {
|
||||
Future<void> acceptJoinRequest(
|
||||
String orgId,
|
||||
String requestId,
|
||||
String role,
|
||||
) async {
|
||||
await _apiClient.post(
|
||||
'/orgs/$orgId/join-requests/$requestId/accept',
|
||||
data: {'role': role},
|
||||
|
||||
@@ -20,10 +20,12 @@ class OrganizationSettingsDialog extends StatefulWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
State<OrganizationSettingsDialog> createState() => _OrganizationSettingsDialogState();
|
||||
State<OrganizationSettingsDialog> createState() =>
|
||||
_OrganizationSettingsDialogState();
|
||||
}
|
||||
|
||||
class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog> with TickerProviderStateMixin {
|
||||
class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
with TickerProviderStateMixin {
|
||||
late TabController _tabController;
|
||||
List<Member> _members = [];
|
||||
List<Invitation> _invitations = [];
|
||||
@@ -77,46 +79,54 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
|
||||
Future<void> _updateMemberRole(String userId, String newRole) async {
|
||||
try {
|
||||
await widget.orgApi.updateMemberRole(widget.organization.id, userId, newRole);
|
||||
await widget.orgApi.updateMemberRole(
|
||||
widget.organization.id,
|
||||
userId,
|
||||
newRole,
|
||||
);
|
||||
await _loadData(); // Refresh
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to update role: $e')),
|
||||
);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Failed to update role: $e')));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _removeMember(String userId) async {
|
||||
try {
|
||||
|
||||
await widget.orgApi.removeMember(widget.organization.id, userId);
|
||||
await _loadData(); // Refresh
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to remove member: $e')),
|
||||
);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Failed to remove member: $e')));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _inviteUser(String username, String role) async {
|
||||
try {
|
||||
|
||||
await widget.orgApi.createInvitation(widget.organization.id, username, role);
|
||||
await widget.orgApi.createInvitation(
|
||||
widget.organization.id,
|
||||
username,
|
||||
role,
|
||||
);
|
||||
await _loadData(); // Refresh
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to send invitation: $e')),
|
||||
);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Failed to send invitation: $e')));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _cancelInvitation(String invitationId) async {
|
||||
try {
|
||||
|
||||
await widget.orgApi.cancelInvitation(widget.organization.id, invitationId);
|
||||
await widget.orgApi.cancelInvitation(
|
||||
widget.organization.id,
|
||||
invitationId,
|
||||
);
|
||||
await _loadData(); // Refresh
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
@@ -128,40 +138,43 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
|
||||
Future<void> _acceptJoinRequest(String requestId, String role) async {
|
||||
try {
|
||||
|
||||
await widget.orgApi.acceptJoinRequest(widget.organization.id, requestId, role);
|
||||
await widget.orgApi.acceptJoinRequest(
|
||||
widget.organization.id,
|
||||
requestId,
|
||||
role,
|
||||
);
|
||||
await _loadData(); // Refresh
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to accept request: $e')),
|
||||
);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Failed to accept request: $e')));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _rejectJoinRequest(String requestId) async {
|
||||
try {
|
||||
|
||||
await widget.orgApi.rejectJoinRequest(widget.organization.id, requestId);
|
||||
await _loadData(); // Refresh
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to reject request: $e')),
|
||||
);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Failed to reject request: $e')));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _regenerateInviteLink() async {
|
||||
try {
|
||||
|
||||
final newLink = await widget.orgApi.regenerateInviteLink(widget.organization.id);
|
||||
final newLink = await widget.orgApi.regenerateInviteLink(
|
||||
widget.organization.id,
|
||||
);
|
||||
setState(() => _inviteLink = newLink);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to regenerate link: $e')),
|
||||
);
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(SnackBar(content: Text('Failed to regenerate link: $e')));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +187,8 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
}
|
||||
}
|
||||
|
||||
bool get _canManage => widget.permissionState is PermissionLoaded &&
|
||||
bool get _canManage =>
|
||||
widget.permissionState is PermissionLoaded &&
|
||||
(widget.permissionState as PermissionLoaded).capabilities.canAdmin;
|
||||
|
||||
@override
|
||||
@@ -232,7 +246,10 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(_error!, style: TextStyle(color: AppTheme.errorColor)),
|
||||
Text(
|
||||
_error!,
|
||||
style: TextStyle(color: AppTheme.errorColor),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ModernGlassButton(
|
||||
onPressed: _loadData,
|
||||
@@ -271,7 +288,8 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
member.role,
|
||||
style: TextStyle(color: AppTheme.secondaryText),
|
||||
),
|
||||
trailing: _canManage ? Row(
|
||||
trailing: _canManage
|
||||
? Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (member.role != 'owner')
|
||||
@@ -291,11 +309,15 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
),
|
||||
if (member.role != 'owner')
|
||||
IconButton(
|
||||
icon: Icon(Icons.remove_circle, color: AppTheme.errorColor),
|
||||
icon: Icon(
|
||||
Icons.remove_circle,
|
||||
color: AppTheme.errorColor,
|
||||
),
|
||||
onPressed: () => _removeMember(member.userId),
|
||||
),
|
||||
],
|
||||
) : null,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -323,8 +345,14 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
itemBuilder: (context, index) {
|
||||
final inv = _invitations[index];
|
||||
return ListTile(
|
||||
title: Text(inv.username, style: TextStyle(color: AppTheme.primaryText)),
|
||||
subtitle: Text('Role: ${inv.role}', style: TextStyle(color: AppTheme.secondaryText)),
|
||||
title: Text(
|
||||
inv.username,
|
||||
style: TextStyle(color: AppTheme.primaryText),
|
||||
),
|
||||
subtitle: Text(
|
||||
'Role: ${inv.role}',
|
||||
style: TextStyle(color: AppTheme.secondaryText),
|
||||
),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.cancel, color: AppTheme.errorColor),
|
||||
onPressed: () => _cancelInvitation(inv.id),
|
||||
@@ -358,10 +386,7 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
DropdownButtonFormField<String>(
|
||||
initialValue: selectedRole,
|
||||
items: ['admin', 'member'].map((role) {
|
||||
return DropdownMenuItem(
|
||||
value: role,
|
||||
child: Text(role),
|
||||
);
|
||||
return DropdownMenuItem(value: role, child: Text(role));
|
||||
}).toList(),
|
||||
onChanged: (value) => selectedRole = value ?? 'member',
|
||||
decoration: const InputDecoration(
|
||||
@@ -399,7 +424,8 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
'Requested to join',
|
||||
style: TextStyle(color: AppTheme.secondaryText),
|
||||
),
|
||||
trailing: _canManage ? Row(
|
||||
trailing: _canManage
|
||||
? Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextButton(
|
||||
@@ -408,10 +434,14 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => _rejectJoinRequest(req.id),
|
||||
child: Text('Reject', style: TextStyle(color: AppTheme.errorColor)),
|
||||
child: Text(
|
||||
'Reject',
|
||||
style: TextStyle(color: AppTheme.errorColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
) : null,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -429,10 +459,7 @@ class _OrganizationSettingsDialogState extends State<OrganizationSettingsDialog>
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
_inviteLink!,
|
||||
style: TextStyle(color: AppTheme.secondaryText),
|
||||
),
|
||||
Text(_inviteLink!, style: TextStyle(color: AppTheme.secondaryText)),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
|
||||
Reference in New Issue
Block a user