Skip to content

Conversation

IronJam11
Copy link
Contributor

@IronJam11 IronJam11 commented Sep 24, 2025

  • Add organisations page
  • Add ABIs of
  1. Organisation Factory
  2. Organisation
  • Add contract write and contract read functiosn for organisation Factory
  • Add "Create Organisation" form page - (tested)
    Corresponding UIs:
Screenshot 2025-09-24 at 10 30 08 PM Screenshot 2025-09-24 at 10 30 20 PM Screenshot 2025-09-24 at 10 30 29 PM

Summary by CodeRabbit

  • New Features

    • Added Organisations section: view your organisations, see details, and create new ones with optional logo upload (IPFS). Accessible via new navigation routes.
  • UI/Style

    • Updated theming with new colors (e.g., borders, shadows) and consistent dimensions for buttons/shadows.
    • Refreshed NFT and Profile screens with theme-based styling, rounded buttons, and improved tiles.
    • Added an Organisations button in the profile.
  • Changes

    • Removed the Live Preview from the Mint NFT coordinates page.
  • Chores

    • Reorganized environment template and enabled env-based organisation contract configuration.

Copy link

coderabbitai bot commented Sep 24, 2025

Walkthrough

Adds 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

Cohort / File(s) Summary
Environment template
/.env.stencil
Reorganized placeholders into grouped sections; same keys, reordered, with blank defaults and updated headers.
Routing and entry
/lib/main.dart
Registers routes for organisations list, details (/organisations/:address), and creation. Imports new pages.
Organisations feature pages
/lib/pages/organisations_pages/create_organisation.dart, /lib/pages/organisations_pages/organisation_details_page.dart, /lib/pages/organisations_pages/user_organisations_page.dart
New UI: create-organisation form with image upload/IPFS and contract write; details page showing address; list page fetching user organisations via contract read and navigating to details/create.
Organisation contract constants
/lib/utils/constants/contract_abis/organisation_contract_details.dart, /lib/utils/constants/contract_abis/organisation_factory_contract_details.dart, /lib/utils/constants/contract_abis/tree_nft_contract_details.dart
Adds dotenv-backed factory/organisation addresses and ABIs; removes obsolete comments from tree NFT details.
Organisation factory services
/lib/utils/services/contract_functions/organisation_factory_contract.dart/organisation_factory_read_functions.dart, /lib/utils/services/contract_functions/organisation_factory_contract.dart/organisation_factory_write_functions.dart, /lib/utils/services/contract_functions/organisation_contract/organisation_read_functions.dart, /lib/utils/services/contract_functions/organisation_contract/organisation_write_functions.dart
New read/write helpers: get user organisations; create organisation with structured result types. Adds empty stubs for organisation contract read/write files.
Tree NFT contract refactor (imports)
/lib/pages/mint_nft/submit_nft_page.dart, /lib/pages/register_user_page.dart, /lib/pages/tree_details_page.dart, /lib/utils/services/contract_functions/tree_nft_contract/tree_nft_contract_read_services.dart, /lib/utils/services/contract_functions/tree_nft_contract/tree_nft_contract_write_functions.dart, /lib/widgets/nft_display_utils/tree_nft_details_verifiers_widget.dart
Switches to specific tree NFT contract details/services; minor read-service cleanups; no functional behavior changes intended.
Theming constants
/lib/utils/constants/ui/color_constants.dart, /lib/utils/constants/ui/dimensions.dart
Adds new theme colors: border, primaryShadow; introduces button radius/blur/border width constants.
Themed UI updates
/lib/widgets/nft_display_utils/user_nfts_widget.dart, /lib/widgets/profile_widgets/profile_section_widget.dart
Applies theme-driven colors, shapes, and dimensions; updates buttons/styles; adds Organisations navigation from profile.
Mint NFT UI trim
/lib/pages/mint_nft/mint_nft_coordinates.dart
Removes Live Preview section and its widget import.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • ceilican
  • bhavik-mangla
  • Zahnentferner

Poem

A nibble of routes, a hop to deploy,
I burrow new pages with carrot-like joy.
Contracts now whisper where addresses stay,
The theme grows greener—hue by day.
I minted no preview, yet wag my ear—
Organisations sprout; the path is clear. 🥕🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “Organisations page” directly references the addition of the new Organisations UI page, which is a core part of this PR’s changeset although it does not call out the related contract ABIs or backend logic.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch organisationsPage

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.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a 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: Import EthereumAddress in write functions file
Add at the top of lib/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 exports treeNftContractAddress. 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 directly

Using toString() and startsWith('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-linter

Reorder 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-linter

Sort 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 ADDRESSES

Also 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 assets

Inlining 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 theming

Full‑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/black

Shadows 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. textPrimary

In 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 and length 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 readability

Minor 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 import

Dead 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/paste

Small 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 param

Keeps 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 paths

If exceptions occur, _isUploading may remain true. Add a finally 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 check

Prevent “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 mode

Use 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 both ContractWriteResult and ContractReadResult 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_packages
lib/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

📥 Commits

Reviewing files that changed from the base of the PR and between d996fc6 and e5ceb55.

📒 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 correct

No API changes observed; usage remains compatible.

lib/pages/tree_details_page.dart (1)

7-8: Switched to specific tree-NFT read/write modules — good consolidation

Consistent 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 — OK

Keeps contract calls scoped to the correct module.

lib/pages/register_user_page.dart (1)

8-8: Import updated to tree-NFT write functions — OK

No 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
Exports treeNFtContractAddress and treeNftContractABI correctly align with their usages in the write/read functions.

lib/main.dart (1)

9-11: LGTM: New organisations pages wired into the app

Imports are correct and scoped.

lib/pages/organisations_pages/create_organisation.dart (1)

8-9: Ignore incorrect import path suggestion The file actually lives in the organisation_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 under lib/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: Confirmed secondaryButton theme color key exists. The secondaryButton entry is defined in getThemeColors; no changes required.

Comment on lines +589 to +592
hintStyle: TextStyle(
color: getThemeColors(context)['background'],
fontSize: 14,
),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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);
Copy link

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.

Comment on lines +71 to +74
UserOrganisationsWidget(
key: _organisationsKey,
userAddress: walletProvider.userAddress.toString()),
],
Copy link

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.

Suggested change
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.

Comment on lines +142 to +146
? _buildUserOrganisationsList(context)
: const Text('No organisations found for this user.'),
if (_isLoading) const CircularProgressIndicator(),
if (_errorMessage.isNotEmpty) Text(_errorMessage),
],
Copy link

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.

Comment on lines +5 to +6
final String organisationContractAddress =
dotenv.env['ORGANISATION_FACTORY_CONTRACT_ADDRESS'] ?? '';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 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.

Comment on lines +3 to +6
final double buttonCircularRadius = 12.0;

final double buttonBlurRadius = 6.0;
final double buttonborderWidth = 2.0;
Copy link

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.

Suggested change
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.

Comment on lines +45 to +48
logger.e("Wallet not connected for minting NFT");
return ContractWriteResult.error(
errorMessage: 'Please connect your wallet before minting.',
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Comment on lines +45 to +46
errorMessage: 'Please connect your wallet before reading NFTs.',
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Comment on lines +70 to +72
final organisations = result.length > 0 ? result[0] ?? [] : [];
final totalCount =
result.length > 1 ? int.parse(result[1].toString()) : 0;
Copy link

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.

Suggested change
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.

Comment on lines +291 to +293
color: tree.death == 0
? getThemeColors(context)['primary']
: getThemeColors(context)['error'],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant