-
Notifications
You must be signed in to change notification settings - Fork 4
Organisations page #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds organisations feature: new pages, routes, and contract helpers for organisation factory (read/write). Refactors several imports to contract-specific services. Updates theming (colors, dimensions) and applies theme-driven UI to profile and NFT widgets. Removes NFT live preview section. Introduces env-driven organisation contract addresses/ABIs. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant App as Flutter App
participant Router as GoRouter
participant Wallet as WalletProvider
participant OFRead as OrgFactory Read
participant OFWrite as OrgFactory Write
participant Chain as Blockchain
participant IPFS as IPFS Service
rect rgb(245,248,255)
note over User,App: View user organisations
User->>App: Open "Organisations"
App->>Router: push /organisations
App->>Wallet: get currentAddress
App->>OFRead: getOrganisationsByUser(wallet)
OFRead->>Chain: call getUserOrganisations(address)
Chain-->>OFRead: {organisations, totalCount}
OFRead-->>App: success(data)
App-->>User: Render list of organisations
end
rect rgb(245,255,245)
note over User,App: Create organisation
User->>App: Tap "Create Organisation"
App->>Router: push /create-organisation
User->>App: Enter name/description
alt optional logo
User->>App: Pick image
App->>IPFS: upload(image)
IPFS-->>App: cid/hash
else no logo
App-->>App: use empty hash
end
App->>Wallet: ensure connected
App->>OFWrite: createOrganisation(name, desc, hash)
OFWrite->>Chain: write createOrganisation(...)
Chain-->>OFWrite: txHash
OFWrite-->>App: success(txHash)
App-->>User: Show success, navigate to /organisations
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
.env.stencil (1)
1-20
: Add!.env.stencil
to.gitignore
Keeps the stencil file tracked while ignoring all other.env
files.lib/utils/services/contract_functions/tree_nft_contract/tree_nft_contract_write_functions.dart (1)
192-195
: ImportEthereumAddress
in write functions file
Add at the top oflib/utils/services/contract_functions/tree_nft_contract/tree_nft_contract_write_functions.dart
:import 'package:web3dart/web3dart.dart' show EthereumAddress;lib/utils/services/contract_functions/tree_nft_contract/tree_nft_contract_read_services.dart (2)
70-74
: Typo in contract address constant breaks compilation
treeNFtContractAddress
has incorrect casing. The details file conventionally exportstreeNftContractAddress
. This will fail to compile.Apply:
- contractAddress: treeNFtContractAddress, + contractAddress: treeNftContractAddress,Repeat the same replacement at Lines 116, 168, 204, and 223.
Also applies to: 116-120, 168-172, 204-208, 223-227
50-57
: Brittle address validation; derive EthereumAddress directlyUsing
toString()
andstartsWith('0x')
is fragile and may reject valid addresses. Prefer null checks and use the typed address when available.Apply:
- final String address = walletProvider.currentAddress.toString(); - if (!address.startsWith('0x')) { - return ContractReadResult.error( - errorMessage: 'Invalid wallet address format', - ); - } - final EthereumAddress userAddress = EthereumAddress.fromHex(address); + final dynamic addr = walletProvider.currentAddress; + if (addr == null) { + return ContractReadResult.error( + errorMessage: 'Wallet address unavailable', + ); + } + final EthereumAddress userAddress = + addr is EthereumAddress ? addr : EthereumAddress.fromHex(addr.toString());
🧹 Nitpick comments (25)
.env.stencil (5)
3-5
: Alphabetize API keys to satisfy dotenv-linterReorder within the section to clear UnorderedKey warnings.
-API_KEY= -API_SECRET= -ALCHEMY_API_KEY= +ALCHEMY_API_KEY= +API_KEY= +API_SECRET=
14-19
: Alphabetize contract address keys (maintain grouping) to satisfy dotenv-linterSort keys within the CONTRACT ADDRESSES section.
-TREE_NFT_CONTRACT_ADDRESS= -ORGANISATION_FACTORY_CONTRACT_ADDRESS= -CARE_TOKEN_CONTRACT_ADDRESS= -VERIFIER_TOKEN_CONTRACT_ADDRESS= -LEGACY_TOKEN_CONTRACT_ADDRESS= -PLANTER_TOKEN_CONTRACT_ADDRESS= +CARE_TOKEN_CONTRACT_ADDRESS= +LEGACY_TOKEN_CONTRACT_ADDRESS= +ORGANISATION_FACTORY_CONTRACT_ADDRESS= +PLANTER_TOKEN_CONTRACT_ADDRESS= +TREE_NFT_CONTRACT_ADDRESS= +VERIFIER_TOKEN_CONTRACT_ADDRESS=
1-1
: Normalize comment headers (space after #, no trailing whitespace)Minor style cleanups to keep headers consistent.
-#API KEYS AND SECRETS +# API KEYS AND SECRETS -#APPLICATION CONFIGURATION +# APPLICATION CONFIGURATION -#CONTRACT ADDRESSES +# CONTRACT ADDRESSESAlso applies to: 7-7, 12-12
12-20
: Clarify contract address expectations (EIP-55 checksums)Add a brief note to avoid casing issues at runtime.
-# CONTRACT ADDRESSES +# CONTRACT ADDRESSES +# All addresses must be EIP-55 checksummed (0x...)
7-11
: Add minimal hints for expected values (reduce setup friction)Tiny comments help new contributors fill values correctly.
-# APPLICATION CONFIGURATION +# APPLICATION CONFIGURATION +# e.g., 11155111 (Sepolia) or 1 (Ethereum mainnet) APPLICATION_CHAIN_ID= +# WalletConnect Cloud Project ID WALLETCONNECT_PROJECT_ID=lib/utils/constants/contract_abis/organisation_contract_details.dart (1)
3-4
: Consider moving ABI JSON to assetsInlining a large ABI string bloats code and hurts readability. Prefer loading from assets (pubspec assets + rootBundle.loadString) or a generated Dart file.
lib/utils/services/contract_functions/organisation_contract/organisation_write_functions.dart (1)
1-2
: Remove unused placeholder file
lib/utils/services/contract_functions/organisation_contract/organisation_write_functions.dart is empty and unreferenced—delete it until needed.lib/utils/services/contract_functions/organisation_contract/organisation_read_functions.dart (1)
1-2
: Remove or stub empty placeholder file
lib/utils/services/contract_functions/organisation_contract/organisation_read_functions.dart
is completely empty; delete it or add a documented stub (similar to organisation_write_functions.dart) to avoid a dead module.lib/utils/constants/ui/color_constants.dart (3)
20-22
: Border color: prefer translucent neutrals for better themingFull‑opaque white/near‑black borders are harsh in UI, especially on dark themes. Use semi‑transparent neutrals for a subtler, more scalable style.
Apply:
- 'border': themeProvider.isDarkMode - ? const Color.fromARGB(255, 255, 255, 255) - : const Color.fromARGB(255, 18, 18, 18), + 'border': themeProvider.isDarkMode + ? Colors.white24 + : Colors.black26,
56-58
: Shadow color should be translucent, not pure white/blackShadows with pure white/black look off. Use semi‑transparent colors for depth that adapts across themes.
Apply:
- 'primaryShadow': themeProvider.isDarkMode - ? const Color.fromARGB(255, 255, 255, 255) - : const Color.fromARGB(255, 0, 0, 0), + 'primaryShadow': themeProvider.isDarkMode + ? Colors.white24 + : Colors.black26,
38-40
: textSecondary looks inverted vs. textPrimaryIn dark mode, secondary text should be lighter than background but dimmer than primary (e.g., white70). In light mode, prefer black54.
Apply:
- 'textSecondary': themeProvider.isDarkMode - ? const Color.fromARGB(255, 0, 0, 0) - : const Color.fromARGB(255, 255, 255, 255), + 'textSecondary': themeProvider.isDarkMode + ? Colors.white70 + : Colors.black54,lib/utils/services/contract_functions/tree_nft_contract/tree_nft_contract_read_services.dart (3)
109-115
: Unnecessary address format check in ping()The contract call doesn’t use the address. Drop the brittle check.
Apply:
- final String address = walletProvider.currentAddress.toString(); - if (!address.startsWith('0x')) { - return ContractReadResult.error( - errorMessage: 'Invalid wallet address format', - ); - }
173-175
: Guard against null/empty contract reads
result
can be null/empty andlength
access will throw. Add a safe guard.Apply:
- final profile = result.length > 0 ? result[0] ?? [] : []; + if (result == null || (result is List && result.isEmpty)) { + return ContractReadResult.error( + errorMessage: 'No data returned from contract', + ); + } + final profile = (result is List && result.isNotEmpty) ? (result[0] ?? []) : [];
81-84
: Use isNotEmpty for readabilityMinor readability improvement.
Apply:
- final trees = result.length > 0 ? result[0] ?? [] : []; - final totalCount = - result.length > 1 ? int.parse(result[1].toString()) : 0; + final trees = result.isNotEmpty ? (result[0] ?? []) : []; + final totalCount = result.length > 1 ? int.parse(result[1].toString()) : 0;lib/utils/constants/ui/dimensions.dart (1)
1-1
: Remove commented importDead code; keep constants files lean.
Apply:
-// import 'package:flutter/material.dart';
lib/pages/organisations_pages/organisation_details_page.dart (1)
15-18
: Make the address selectable for copy/pasteSmall UX win.
Apply:
- child: Text( - "Organisation Address: $organisationAddress", - style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), - ), + child: SelectableText( + "Organisation Address: $organisationAddress", + style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ),lib/main.dart (1)
69-85
: Consider centralizing these paths in RouteConstants and validating the address paramKeeps route strings consistent and allows future guard (e.g., hex address validation) without scattered changes.
No diff necessary.
lib/pages/organisations_pages/create_organisation.dart (4)
51-75
: Ensure _isUploading resets on all code pathsIf exceptions occur,
_isUploading
may remain true. Add afinally
safeguard.Apply:
- Future<void> _uploadImageToIPFS() async { + Future<void> _uploadImageToIPFS() async { if (_selectedImage == null) return; try { final hash = await uploadToIPFS(_selectedImage!, (uploading) { setState(() { _isUploading = uploading; }); }); if (hash != null) { setState(() { _uploadedImageHash = hash; }); _showCustomSnackBar("Image uploaded successfully!"); } else { _showCustomSnackBar("Failed to upload image", isError: true); } } catch (e) { _showCustomSnackBar( "Error uploading image: $e", isError: true, ); + } finally { + if (mounted) { + setState(() => _isUploading = false); + } } }
101-122
: Avoid using BuildContext after await without a mounted checkPrevent “use_build_context_synchronously” issues and NPEs when the widget unmounts during async work.
Apply:
- final result = - await OrganisationFactoryContractWriteFunctions.createOrganisation( + final result = + await OrganisationFactoryContractWriteFunctions.createOrganisation( walletProvider: walletProvider, name: name, description: description, organisationPhotoHash: _uploadedImageHash ?? ""); - _showCustomSnackBar("Organisation details submitted successfully!"); + if (!mounted) return; + _showCustomSnackBar("Organisation details submitted successfully!"); @@ - // ignore: use_build_context_synchronously - context.push('/organisations'); + if (!mounted) return; + context.push('/organisations'); // consider context.go(...) if you want to replace
162-166
: Page title likely should reflect the action“Organisation Details” reads like a view page. For a creation form, “Create Organisation” is clearer.
Apply:
- title: "Organisation Details", + title: "Create Organisation",
375-383
: Hardcoded light theme styles break dark modeUse theme colors for container background and borders.
Apply:
- Container( + Container( width: double.infinity, decoration: BoxDecoration( - color: Colors.white, + color: getThemeColors(context)['background'], borderRadius: BorderRadius.circular(16), border: Border.all( - color: const Color(0xFFFAEB96), - width: 2, + color: getThemeColors(context)['border']!, + width: 2, ), ),lib/utils/services/contract_functions/organisation_factory_contract.dart/organisation_factory_contract_write_functions.dart (2)
41-41
: Remove unused parameter.The
additionalData
parameter is defined but never used in the function.- String additionalData = "",
5-33
: Consider sharing ContractWriteResult with read functions.Both write and read function files define similar result classes. Consider extracting to a shared module to follow DRY principles.
Consider creating a shared file
lib/utils/services/contract_functions/contract_result.dart
to house bothContractWriteResult
andContractReadResult
classes, or use a generic result type.lib/utils/services/contract_functions/organisation_factory_contract.dart/organisation_factory_read_functions.dart (1)
1-1
: Remove or fix the ignore comment.The ignore comment should be removed if the dependency is properly declared, or the comment should be fixed to the correct format.
Either remove the comment if web3dart is in pubspec.yaml, or fix it:
-// ignore: depend_on_referenced_packages +// ignore_for_file: depend_on_referenced_packageslib/pages/organisations_pages/user_organisations_page.dart (1)
161-191
: Add truncation for long organisation addresses.Organisation addresses are typically 42 characters (0x + 40 hex chars) which might overflow on smaller screens.
Add address truncation similar to profile widget:
- child: Text( - organisationAddress, - style: TextStyle( - color: getThemeColors(context)['textPrimary'], - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), + child: Row( + children: [ + Expanded( + child: Text( + '${organisationAddress.substring(0, 6)}...${organisationAddress.substring(organisationAddress.length - 4)}', + style: TextStyle( + color: getThemeColors(context)['textPrimary'], + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + Icon(Icons.arrow_forward_ios, size: 16, color: getThemeColors(context)['icon']), + ], + ),
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (23)
.env.stencil
(1 hunks)lib/main.dart
(2 hunks)lib/pages/mint_nft/mint_nft_coordinates.dart
(0 hunks)lib/pages/mint_nft/submit_nft_page.dart
(1 hunks)lib/pages/organisations_pages/create_organisation.dart
(1 hunks)lib/pages/organisations_pages/organisation_details_page.dart
(1 hunks)lib/pages/organisations_pages/user_organisations_page.dart
(1 hunks)lib/pages/register_user_page.dart
(1 hunks)lib/pages/tree_details_page.dart
(1 hunks)lib/utils/constants/contract_abis/organisation_contract_details.dart
(1 hunks)lib/utils/constants/contract_abis/organisation_factory_contract_details.dart
(1 hunks)lib/utils/constants/contract_abis/tree_nft_contract_details.dart
(0 hunks)lib/utils/constants/ui/color_constants.dart
(2 hunks)lib/utils/constants/ui/dimensions.dart
(1 hunks)lib/utils/services/contract_functions/organisation_contract/organisation_read_functions.dart
(1 hunks)lib/utils/services/contract_functions/organisation_contract/organisation_write_functions.dart
(1 hunks)lib/utils/services/contract_functions/organisation_factory_contract.dart/organisation_factory_contract_write_functions.dart
(1 hunks)lib/utils/services/contract_functions/organisation_factory_contract.dart/organisation_factory_read_functions.dart
(1 hunks)lib/utils/services/contract_functions/tree_nft_contract/tree_nft_contract_read_services.dart
(1 hunks)lib/utils/services/contract_functions/tree_nft_contract/tree_nft_contract_write_functions.dart
(1 hunks)lib/widgets/nft_display_utils/tree_nft_details_verifiers_widget.dart
(1 hunks)lib/widgets/nft_display_utils/user_nfts_widget.dart
(4 hunks)lib/widgets/profile_widgets/profile_section_widget.dart
(4 hunks)
💤 Files with no reviewable changes (2)
- lib/utils/constants/contract_abis/tree_nft_contract_details.dart
- lib/pages/mint_nft/mint_nft_coordinates.dart
🧰 Additional context used
🪛 dotenv-linter (3.3.0)
.env.stencil
[warning] 5-5: [UnorderedKey] The ALCHEMY_API_KEY key should go before the API_KEY key
(UnorderedKey)
[warning] 15-15: [UnorderedKey] The ORGANISATION_FACTORY_CONTRACT_ADDRESS key should go before the TREE_NFT_CONTRACT_ADDRESS key
(UnorderedKey)
[warning] 16-16: [UnorderedKey] The CARE_TOKEN_CONTRACT_ADDRESS key should go before the ORGANISATION_FACTORY_CONTRACT_ADDRESS key
(UnorderedKey)
[warning] 18-18: [UnorderedKey] The LEGACY_TOKEN_CONTRACT_ADDRESS key should go before the ORGANISATION_FACTORY_CONTRACT_ADDRESS key
(UnorderedKey)
[warning] 19-19: [UnorderedKey] The PLANTER_TOKEN_CONTRACT_ADDRESS key should go before the TREE_NFT_CONTRACT_ADDRESS key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (15)
lib/pages/mint_nft/submit_nft_page.dart (1)
9-9
: Import path refactor to tree-NFT write functions is correctNo API changes observed; usage remains compatible.
lib/pages/tree_details_page.dart (1)
7-8
: Switched to specific tree-NFT read/write modules — good consolidationConsistent with the service split introduced in this PR.
lib/widgets/nft_display_utils/tree_nft_details_verifiers_widget.dart (1)
7-7
: Import updated to tree-NFT write functions — OKKeeps contract calls scoped to the correct module.
lib/pages/register_user_page.dart (1)
8-8
: Import updated to tree-NFT write functions — OKNo behavioral changes needed here.
lib/utils/services/contract_functions/tree_nft_contract/tree_nft_contract_write_functions.dart (1)
3-3
: Approve: exported identifiers match usages
ExportstreeNFtContractAddress
andtreeNftContractABI
correctly align with their usages in the write/read functions.lib/main.dart (1)
9-11
: LGTM: New organisations pages wired into the appImports are correct and scoped.
lib/pages/organisations_pages/create_organisation.dart (1)
8-9
: Ignore incorrect import path suggestion The file actually lives in theorganisation_factory_contract.dart
directory, so the existing import is valid.Likely an incorrect or invalid review comment.
lib/widgets/nft_display_utils/user_nfts_widget.dart (4)
6-6
: LGTM! Good refactor to use theme dimensions.The addition of the dimensions import aligns well with the theme-based UI approach.
220-221
: Excellent theme migration for better consistency.The systematic replacement of hardcoded colors with theme-based colors improves maintainability and supports future theme switching capabilities.
Also applies to: 227-228, 250-251, 255-256, 264-265, 269-270, 277-278, 282-283
315-318
: Great consistency with theme-driven button styling.The rounded border radius using
buttonCircularRadius
from dimensions provides consistent button styling across the app.Also applies to: 335-338
8-8
: Import path is correct:tree_nft_contract_read_services.dart
exists underlib/utils/services/contract_functions/tree_nft_contract
, matching the import.lib/widgets/profile_widgets/profile_section_widget.dart (4)
6-6
: LGTM! Consistent theme imports.The imports align with the app-wide theme refactoring approach.
Also applies to: 8-8
220-239
: Good addition of the Organisations navigation button.The button properly navigates to the new organisations page and follows the established styling patterns.
249-275
: Excellent refactor of token widgets to Material design.The token display blocks now use Material components with proper elevation and consistent theme colors. This improves visual hierarchy and maintains design consistency.
Also applies to: 277-302, 304-330, 331-358
222-223
: ConfirmedsecondaryButton
theme color key exists. ThesecondaryButton
entry is defined in getThemeColors; no changes required.
hintStyle: TextStyle( | ||
color: getThemeColors(context)['background'], | ||
fontSize: 14, | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hint text color uses background color (invisible in light theme)
Hints should use a subdued text color, not the background.
Apply:
- hintStyle: TextStyle(
- color: getThemeColors(context)['background'],
- fontSize: 14,
- ),
+ hintStyle: TextStyle(
+ color: getThemeColors(context)['textSecondary'],
+ fontSize: 14,
+ ),
🤖 Prompt for AI Agents
In lib/pages/organisations_pages/create_organisation.dart around lines 589 to
592, the TextStyle for hintStyle incorrectly uses the theme 'background' color
(which is invisible in light theme); change the color to a subdued hint color
such as Theme.of(context).hintColor or your theme's 'muted'/'secondary' text
color (e.g. getThemeColors(context)['muted']) so placeholder text is visible
across themes, leaving fontSize unchanged.
|
||
@override | ||
Widget build(BuildContext context) { | ||
final walletProvider = Provider.of<WalletProvider>(context); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
🧩 Analysis chain
Verify userAddress usage.
The walletProvider.userAddress
is obtained but the widget also receives userAddress
as a parameter which seems unused.
🏁 Script executed:
#!/bin/bash
# Check how userAddress is used in the widget
rg -n "widget\.userAddress" lib/pages/organisations_pages/user_organisations_page.dart
# Check what userAddress property exists on WalletProvider
rg -n "userAddress" lib/providers/wallet_provider.dart
Length of output: 30
Remove unused userAddress
constructor parameter
The userAddress
passed into UserOrganisationsPage
is never referenced (and WalletProvider.userAddress
currently returns null); remove the parameter or switch your code to use the passed-in value instead of the provider getter.
🤖 Prompt for AI Agents
In lib/pages/organisations_pages/user_organisations_page.dart around line 24,
the constructor parameter userAddress is never used while the code reads
WalletProvider from Provider.of(context); either remove the unused userAddress
parameter from the UserOrganisationsPage constructor and delete any unused
field/assignments and update all call sites that pass it, or alter the widget to
actually use the passed-in value (replace accesses to WalletProvider.userAddress
with the widget.userAddress) and ensure the constructor and field are
non-nullable/validated as needed; update imports/usages accordingly so there are
no unused parameter warnings or null-return reliance on the provider.
UserOrganisationsWidget( | ||
key: _organisationsKey, | ||
userAddress: walletProvider.userAddress.toString()), | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
🧩 Analysis chain
Verify the widget parent structure.
The UserOrganisationsWidget
is placed inside a Column without being wrapped in an Expanded widget, which could cause overflow issues if the list grows.
Wrap the widget in Expanded to prevent overflow:
- UserOrganisationsWidget(
- key: _organisationsKey,
- userAddress: walletProvider.userAddress.toString()),
+ Expanded(
+ child: UserOrganisationsWidget(
+ key: _organisationsKey,
+ userAddress: walletProvider.userAddress.toString()),
+ ),
🏁 Script executed:
#!/bin/bash
set -e
# Locate the UserOrganisationsWidget usage with context
rg -nC5 "UserOrganisationsWidget" lib/pages/organisations_pages/user_organisations_page.dart
# Locate the surrounding Column definition
rg -nC10 "Column" lib/pages/organisations_pages/user_organisations_page.dart
Length of output: 2633
🏁 Script executed:
#!/bin/bash
set -e
# Find the definition of _buildUserOrganisationsList
rg -n -C5 "_buildUserOrganisationsList" lib/pages/organisations_pages/user_organisations_page.dart
Length of output: 730
Wrap UserOrganisationsWidget in Expanded to prevent overflow
The widget is inside a Column without height constraints; using Expanded will allocate remaining space and let its internal ListView scroll:
- UserOrganisationsWidget(
- key: _organisationsKey,
- userAddress: walletProvider.userAddress.toString()),
+ Expanded(
+ child: UserOrganisationsWidget(
+ key: _organisationsKey,
+ userAddress: walletProvider.userAddress.toString()),
+ ),
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
UserOrganisationsWidget( | |
key: _organisationsKey, | |
userAddress: walletProvider.userAddress.toString()), | |
], | |
Expanded( | |
child: UserOrganisationsWidget( | |
key: _organisationsKey, | |
userAddress: walletProvider.userAddress.toString()), | |
), | |
], |
🤖 Prompt for AI Agents
In lib/pages/organisations_pages/user_organisations_page.dart around lines 71 to
74, the UserOrganisationsWidget is placed directly inside a Column causing
overflow because it has unbounded height; wrap that widget with Expanded
(preserving the existing key and userAddress args) so it takes remaining space
and lets its internal ListView scroll, e.g. replace the direct widget with
Expanded(child: UserOrganisationsWidget(...)) to resolve the overflow.
? _buildUserOrganisationsList(context) | ||
: const Text('No organisations found for this user.'), | ||
if (_isLoading) const CircularProgressIndicator(), | ||
if (_errorMessage.isNotEmpty) Text(_errorMessage), | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve error and loading state UI layout.
The current implementation stacks loading indicator and error messages below the "No organisations" text, which could cause layout issues.
Refactor to show mutually exclusive states:
- return Column(
- children: [
- userOrganisations.isNotEmpty
- ? _buildUserOrganisationsList(context)
- : const Text('No organisations found for this user.'),
- if (_isLoading) const CircularProgressIndicator(),
- if (_errorMessage.isNotEmpty) Text(_errorMessage),
- ],
- );
+ if (_isLoading) {
+ return const Center(child: CircularProgressIndicator());
+ }
+
+ if (_errorMessage.isNotEmpty) {
+ return Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Icon(Icons.error_outline, size: 48, color: getThemeColors(context)['error']),
+ const SizedBox(height: 16),
+ Text(_errorMessage, style: TextStyle(color: getThemeColors(context)['error'])),
+ const SizedBox(height: 16),
+ ElevatedButton(
+ onPressed: fetchUserOrganisations,
+ child: const Text('Retry'),
+ ),
+ ],
+ ),
+ );
+ }
+
+ return userOrganisations.isNotEmpty
+ ? _buildUserOrganisationsList(context)
+ : const Center(child: Text('No organisations found for this user.'));
🤖 Prompt for AI Agents
In lib/pages/organisations_pages/user_organisations_page.dart around lines 142
to 146, the loading indicator and error Text are conditionally added alongside
the "No organisations" message causing overlapping layout; refactor to present
mutually exclusive UI states by replacing the separate ifs with a single
conditional block that returns exactly one widget: when _isLoading show a
centered CircularProgressIndicator, else if _errorMessage.isNotEmpty show the
error Text (styled/centered), else show the organisations list or the "No
organisations found" message; ensure this block is placed where the current
stacked children are so only one of loading/error/content renders at a time.
final String organisationContractAddress = | ||
dotenv.env['ORGANISATION_FACTORY_CONTRACT_ADDRESS'] ?? ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Wrong env var used for organisation contract address
organisationContractAddress
reads ORGANISATION_FACTORY_CONTRACT_ADDRESS
. That’s the factory, not the organisation contract. If you keep a single default address, point it to the correct env var; otherwise remove this constant and pass addresses dynamically (factory returns per‑org addresses).
Apply if you intend a single default org contract address:
-final String organisationContractAddress =
- dotenv.env['ORGANISATION_FACTORY_CONTRACT_ADDRESS'] ?? '';
+final String organisationContractAddress =
+ dotenv.env['ORGANISATION_CONTRACT_ADDRESS'] ?? '';
If org addresses are per‑instance (recommended), remove this constant entirely and require callers to provide the address.
-final String organisationContractAddress =
- dotenv.env['ORGANISATION_FACTORY_CONTRACT_ADDRESS'] ?? '';
Verify current usages and env keys:
🏁 Script executed:
#!/bin/bash
rg -n -C2 'organisationContractAddress|ORGANISATION_FACTORY_CONTRACT_ADDRESS|ORGANISATION_CONTRACT_ADDRESS'
Length of output: 13344
Use correct env var for organisationContractAddress
In lib/utils/constants/contract_abis/organisation_contract_details.dart you’re reading the factory address (ORGANISATION_FACTORY_CONTRACT_ADDRESS
) instead of the organisation contract. To fix:
If you intend a static default address:
-final String organisationContractAddress =
- dotenv.env['ORGANISATION_FACTORY_CONTRACT_ADDRESS'] ?? '';
+final String organisationContractAddress =
+ dotenv.env['ORGANISATION_CONTRACT_ADDRESS'] ?? '';
If addresses are fetched per-organisation via the factory, remove this constant and require callers to supply the address.
🤖 Prompt for AI Agents
In lib/utils/constants/contract_abis/organisation_contract_details.dart around
lines 5-6, the constant is reading the factory address env var
(ORGANISATION_FACTORY_CONTRACT_ADDRESS) instead of the organisation contract;
either change the lookup to the correct env var name (e.g.
dotenv.env['ORGANISATION_CONTRACT_ADDRESS'] ?? '<static-default-address>') if
you want a static default, or remove this constant entirely and update callers
to accept/require the organisation contract address provided by the factory at
runtime.
final double buttonCircularRadius = 12.0; | ||
|
||
final double buttonBlurRadius = 6.0; | ||
final double buttonborderWidth = 2.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
🧩 Analysis chain
Use consts and fix naming; keep a backward-compatible alias
Constants should be const
. Also correct buttonborderWidth
casing; retain an alias to avoid breaking call sites.
Apply:
-final double buttonCircularRadius = 12.0;
-
-final double buttonBlurRadius = 6.0;
-final double buttonborderWidth = 2.0;
+const double buttonCircularRadius = 12.0;
+
+const double buttonBlurRadius = 6.0;
+const double buttonBorderWidth = 2.0;
+@Deprecated('Use buttonBorderWidth instead')
+const double buttonborderWidth = buttonBorderWidth;
Run to update any remaining uses:
🏁 Script executed:
#!/bin/bash
rg -n "buttonborderWidth|buttonBorderWidth|buttonBlurRadius|buttonCircularRadius" -g '!**/build/**'
Length of output: 148
🏁 Script executed:
#!/bin/bash
# Locate and display the dimensions.dart file
file=$(fd dimensions.dart | head -n1)
if [ -z "$file" ]; then
echo "dimensions.dart not found"
exit 0
fi
echo "=== $file ==="
sed -n '1,50p' "$file"
# Search for any references to these constants across Dart files
echo "=== References ==="
rg -n -C1 --type dart 'buttonborderWidth|buttonBorderWidth|buttonBlurRadius|buttonCircularRadius' -g '!build/**'
Length of output: 376
🏁 Script executed:
#!/bin/bash
# Search all Dart files (excluding build/) for any references to these constants
rg -n -C1 'buttonborderWidth|buttonBorderWidth|buttonBlurRadius|buttonCircularRadius' -g '*.dart' -g '!build/**'
Length of output: 5700
Use const and add deprecated alias for buttonborderWidth
Constants should be const
; rename buttonborderWidth
to buttonBorderWidth
and add a deprecated alias for backward compatibility.
--- lib/utils/constants/ui/dimensions.dart
-final double buttonCircularRadius = 12.0;
-
-final double buttonBlurRadius = 6.0;
-final double buttonborderWidth = 2.0;
+const double buttonCircularRadius = 12.0;
+
+const double buttonBlurRadius = 6.0;
+const double buttonBorderWidth = 2.0;
+@Deprecated('Use buttonBorderWidth instead')
+const double buttonborderWidth = buttonBorderWidth;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
final double buttonCircularRadius = 12.0; | |
final double buttonBlurRadius = 6.0; | |
final double buttonborderWidth = 2.0; | |
const double buttonCircularRadius = 12.0; | |
const double buttonBlurRadius = 6.0; | |
const double buttonBorderWidth = 2.0; | |
@Deprecated('Use buttonBorderWidth instead') | |
const double buttonborderWidth = buttonBorderWidth; |
🤖 Prompt for AI Agents
In lib/utils/constants/ui/dimensions.dart around lines 3 to 6, the numeric
constants should be declared as const and the misspelled identifier
buttonborderWidth should be renamed to buttonBorderWidth; update the three
declarations to use const, change buttonborderWidth to const double
buttonBorderWidth = 2.0, and add a deprecated alias for backwards compatibility
(e.g., annotate the old name with @deprecated or @Deprecated and assign it to
the new constant) so existing usages keep working while new code uses
buttonBorderWidth.
logger.e("Wallet not connected for minting NFT"); | ||
return ContractWriteResult.error( | ||
errorMessage: 'Please connect your wallet before minting.', | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix inconsistent error messaging.
The error messages reference "NFT" operations but this is for organisation creation.
Apply this diff to fix the messages:
- logger.e("Wallet not connected for minting NFT");
+ logger.e("Wallet not connected for creating organisation");
return ContractWriteResult.error(
- errorMessage: 'Please connect your wallet before minting.',
+ errorMessage: 'Please connect your wallet before creating an organisation.',
);
- logger.i("NFT minting transaction sent: $txHash");
+ logger.i("Organisation creation transaction sent: $txHash");
- logger.e("Error minting NFT", error: e);
+ logger.e("Error creating organisation", error: e);
Also applies to: 60-60, 71-71
🤖 Prompt for AI Agents
In
lib/utils/services/contract_functions/organisation_factory_contract.dart/organisation_factory_contract_write_functions.dart
around lines 45-48 (also apply same fix at lines 60 and 71), the error messages
incorrectly reference "NFT"; change those log and returned error messages to
reference organisation creation instead — e.g., update logger.e("Wallet not
connected for minting NFT") to logger.e("Wallet not connected for creating
organisation") and change the ContractWriteResult.error message 'Please connect
your wallet before minting.' to 'Please connect your wallet before creating an
organisation.' Apply the same substitution for the other occurrences at lines 60
and 71.
errorMessage: 'Please connect your wallet before reading NFTs.', | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix inconsistent error messages referencing NFTs.
Similar to the write functions, the error messages incorrectly reference NFTs instead of organisations.
Apply this diff:
- errorMessage: 'Please connect your wallet before reading NFTs.',
+ errorMessage: 'Please connect your wallet before reading organisations.',
- errorMessage: 'Failed to read NFTs: ${e.toString()}',
+ errorMessage: 'Failed to read organisations: ${e.toString()}',
Also applies to: 83-83
🤖 Prompt for AI Agents
In
lib/utils/services/contract_functions/organisation_factory_contract.dart/organisation_factory_read_functions.dart
around lines 45-46 (and also line 83), update the inconsistent error messages
that reference "NFTs" to instead reference "organisations": replace 'Please
connect your wallet before reading NFTs.' (and any other occurrences at the
mentioned lines) with 'Please connect your wallet before reading organisations.'
to match the organisation read functions.
final organisations = result.length > 0 ? result[0] ?? [] : []; | ||
final totalCount = | ||
result.length > 1 ? int.parse(result[1].toString()) : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add safer array access with bounds checking.
The code accesses array indices without proper bounds checking.
Apply this diff for safer access:
- final organisations = result.length > 0 ? result[0] ?? [] : [];
- final totalCount =
- result.length > 1 ? int.parse(result[1].toString()) : 0;
+ final organisations = result.isNotEmpty ? (result[0] ?? []) : [];
+ final totalCount = result.length > 1
+ ? int.tryParse(result[1].toString()) ?? 0
+ : 0;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
final organisations = result.length > 0 ? result[0] ?? [] : []; | |
final totalCount = | |
result.length > 1 ? int.parse(result[1].toString()) : 0; | |
// Replace bounds-checked access and safer parsing | |
final organisations = result.isNotEmpty ? (result[0] ?? []) : []; | |
final totalCount = result.length > 1 | |
? int.tryParse(result[1].toString()) ?? 0 | |
: 0; |
🤖 Prompt for AI Agents
In
lib/utils/services/contract_functions/organisation_factory_contract.dart/organisation_factory_read_functions.dart
around lines 70 to 72, the array is accessed without robust bounds/null/type
checks; change to safely read result[0] and result[1] only after verifying
result is not null and result.length > index, coerce result[0] to a list (or use
an empty list) if it's null, and parse result[1] using a safe approach (e.g.,
check for null, call toString(), then use int.tryParse with fallback 0) so you
avoid out-of-range, null, or parse errors.
color: tree.death == 0 | ||
? getThemeColors(context)['primary'] | ||
: getThemeColors(context)['error'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix inverted status indicator logic.
The condition appears to be backwards - when tree.death == 0
(tree is alive), it should show 'primary' color, but the text below shows 'Deceased' when tree.death < current_time
.
Apply this diff to fix the logic:
- color: tree.death == 0
- ? getThemeColors(context)['primary']
- : getThemeColors(context)['error'],
+ color: tree.death == 0 || tree.death > DateTime.now().millisecondsSinceEpoch ~/ 1000
+ ? getThemeColors(context)['primary']
+ : getThemeColors(context)['error'],
🤖 Prompt for AI Agents
In lib/widgets/nft_display_utils/user_nfts_widget.dart around lines 291-293, the
color condition is inconsistent with the textual status check and currently
treats death==0 as primary but everything else as error; change the logic so the
error color is only used when the tree has a non-zero death timestamp that is in
the past (i.e. tree.death != 0 && tree.death < current_time), otherwise use the
primary color (covers death==0 and future death timestamps).
Corresponding UIs:
Summary by CodeRabbit
New Features
UI/Style
Changes
Chores