Skip to content
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

Master into develop #132

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open

Master into develop #132

wants to merge 6 commits into from

Conversation

tomislavmamic
Copy link
Member

@tomislavmamic tomislavmamic commented Feb 25, 2025

Summary by CodeRabbit

  • New Features

    • Refreshed project discovery with dynamic board and map views.
    • Introduced neighborhood filtering for tailored project browsing.
    • Enhanced project pages with dynamic links and improved donation inputs.
    • Added conditional navigation options for easier project access.
  • Documentation

    • Rebranded project overview with updated contributor guidelines and clearer community resources.
  • Style

    • Improved layout and responsive design for header, footer, and social sections, resulting in a more polished and user-friendly interface.

Copy link

coderabbitai bot commented Feb 25, 2025

Walkthrough

This pull request introduces extensive updates across the Zazelenimo project. Key changes include documentation and rebranding updates (e.g. CONTRIBUTING.md, README.md), new configuration and environment variables, localization tweaks, and UI improvements in core components such as header, footer, project cards, and layouts. Several outdated pages have been removed while new functionalities—like round ID management via context, enhanced file handling via a custom hook, neighborhood filtering in project lists, and expanded proposal submission logic—have been added. Dependency sources in the kit packages have also been updated.

Changes

File(s) Change Summary
.gitignore, CONTRIBUTING.md, FUNDING.json, README.md Added new documentation files, updated ignore patterns, rebranded project title, and reorganized README content.
apps/platform/.env.example, .../next.config.mjs, turbo.json Introduced new environment variables (e.g. NEXT_PUBLIC_URL, Optimism Sepolia keys, feature flags) and dynamic IPFS image configuration.
apps/platform/messages/en.json, apps/platform/messages/hr.json Updated localization files with new keys and rephrased descriptions for clarity.
apps/platform/src/app/Header.tsx, LanguageSwitcher.tsx, Navigation.tsx, RoundPhase.tsx, AddToCart.tsx, CartProjectCard.tsx, Icons.tsx, Socials.tsx, Footer.tsx, FooterLinks.tsx, FooterRoundId.tsx, HomepageAbout.tsx, HomepageIntro.tsx, ProjectCard.tsx, ProjectDetails.tsx, ProjectSidebar.tsx, ProjectSocialIcons.tsx, NeighborhoodSelector.tsx, ProjectList.tsx, ProjectListHeader.tsx, ProjectListMap.tsx Refined UI components with adjustments to spacing, conditional rendering, dynamic links, responsive layout changes, and enhanced interactivity including new icons and a dedicated round ID input component.
apps/platform/src/app/[chainId]/**/* Removed outdated page components related to rounds and application proposals.
apps/platform/src/app/contexts/roundIdContext.tsx, useFileHandler.ts, .../hooks/useDebounce.ts Added new context and hooks for round ID management, file handling, and debouncing input.
apps/platform/src/app/projects/page.tsx, apps/platform/src/app/projects/propose/page.tsx, .../propose/actions.ts Introduced enhanced project proposal submission flows with localStorage persistence, countdown redirect, and neighborhood filtering in project lists.
apps/platform/src/data/sample_content/applications.json, apps/platform/tailwind.config.ts Added sample project data and centralized color, keyframe, and animation configurations.
Packages in packages/kit/... Updated dependencies and import sources from @gitcoin/gitcoin-chain-data to @b0rza/gitcoin-chain-data; refined types, hooks, API providers, strategies, and configuration files accordingly.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant CP as CreateProjectPage
    participant FH as useFileHandler
    participant LS as LocalStorage
    participant R as Router
    U->>CP: Fill proposal details & select files
    CP->>FH: Trigger file selection (handleFileChange)
    FH-->>CP: Return selected files with preview
    CP->>LS: Save proposal form data
    CP->>CP: Start countdown timer
    Note right of CP: Wait for 15 seconds
    CP->>R: Redirect to proposal topic page
Loading
sequenceDiagram
    participant U as User
    participant F as Footer
    participant FR as FooterRoundId
    participant RC as RoundIdContext
    U->>F: Load footer
    F->>FR: Check NEXT_PUBLIC_ALLOW_ROUND_INPUT
    FR->>RC: Read current round id
    U->>FR: Update round id via input
    FR->>RC: Set new round id
    Note over RC: Round id updated in context
Loading

Poem

I’m a rabbit with a joyful code hop,
In fields of updates, I never stop.
New hooks and contexts make paths so clear,
While UI blooms with every feature here.
I nibble bugs away with a twitch of delight—
Bursting with bytes in a garden so bright!
🐰🌿

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

vercel bot commented Feb 25, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
zazelenimo ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 25, 2025 3:00pm

@tomislavmamic tomislavmamic changed the title Master Master into develop Feb 25, 2025
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: 9

🧹 Nitpick comments (23)
apps/platform/src/app/components/footer/FooterRoundId.tsx (1)

1-24: Inconsistent indentation in the component

The file has mixed indentation - some lines use tabs while others use spaces, which affects code readability and maintainability.

Consider standardizing the indentation throughout the file to use either spaces or tabs consistently.

apps/platform/src/app/hooks/useFileHandler.ts (1)

8-58: File validation and constraints missing

The hook doesn't include any validation for file types, sizes, or limits on the number of files. This could lead to unexpected behavior or poor user experience if inappropriate files are selected.

Consider adding file validation options and constraints:

- export default function useFileHandler() {
+ export default function useFileHandler(options?: {
+   maxFiles?: number;
+   maxSizeInBytes?: number;
+   acceptedFileTypes?: string[];
+ }) {
	const [selectedFiles, setSelectedFiles] = useState<FileWithPreview[]>([]);
	const inputRef = useRef<HTMLInputElement | null>(null);
+	const [errors, setErrors] = useState<string[]>([]);

	// Handle file input change
	const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
		const files: File[] = event.target.files
			? Array.from(event.target.files)
			: [];
+		
+		// Validate files
+		const validationErrors: string[] = [];
+		
+		if (options?.maxFiles && selectedFiles.length + files.length > options.maxFiles) {
+			validationErrors.push(`You can only upload up to ${options.maxFiles} files.`);
+			return setErrors(validationErrors);
+		}
+		
+		const validFiles = files.filter(file => {
+			if (options?.maxSizeInBytes && file.size > options?.maxSizeInBytes) {
+				validationErrors.push(`File "${file.name}" exceeds the maximum size.`);
+				return false;
+			}
+			
+			if (options?.acceptedFileTypes && !options.acceptedFileTypes.includes(file.type)) {
+				validationErrors.push(`File "${file.name}" type is not supported.`);
+				return false;
+			}
+			
+			return true;
+		});
+		
+		setErrors(validationErrors);

-		// Map files to include a preview URL
-		const filePreviews: FileWithPreview[] = files.map(file => ({
+		// Map valid files to include a preview URL
+		const filePreviews: FileWithPreview[] = validFiles.map(file => ({
			file,
			url: URL.createObjectURL(file),
		}));

		setSelectedFiles(prevFiles => [...prevFiles, ...filePreviews]);
	};

	// Rest of the code remains the same...

	return {
		selectedFiles,
		handleFileChange,
		openFilePicker,
		removeFile,
		inputRef,
+		errors,
	};
}
apps/platform/src/app/projects/page.tsx (4)

56-59: Remove console.log statement

The console.log statement in the useEffect hook should be removed in production code to avoid cluttering the console.

	useEffect(() => {
-		console.log('debouncedRoundId', debouncedRoundId);
		refetch();
	}, [debouncedRoundId, refetch]);

52-54: Improve error handling

The component logs errors to the console but doesn't provide any feedback to the user. Consider adding a user-friendly error message.

+	const [error, setError] = useState<string | null>(null);

	if (isError) {
		console.error(error);
+		setError('Failed to load projects. Please try again later.');
	}

	// Then in the render method, add:
+	{error && (
+		<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
+			<span className="block sm:inline">{error}</span>
+		</div>
+	)}

65-83: Add loading state indicator

The component does not indicate when it's loading data, which may lead to a poor user experience. Consider adding a loading state indicator.

+	const { data, refetch, isError, error, isLoading } = useApplications(query, extendApplicationData);

	// Then in the render method, update:
	{apps && (
		<>
			{activeTab === 'board' && <ProjectList applications={apps} />}
			{activeTab === 'map' && <ProjectListMap applications={apps} />}
		</>
	)}
+	{isLoading && (
+		<div className="flex justify-center items-center h-40">
+			<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-green-500"></div>
+		</div>
+	)}

61-63: Add type safety to tab handling

The current implementation accepts any string as a tab value, which could lead to runtime errors. Consider using a union type for better type safety.

+	type TabType = 'board' | 'map';
-	const [activeTab, setActiveTab] = useState('board');
+	const [activeTab, setActiveTab] = useState<TabType>('board');

-	const handleTabChange = (tab: string) => {
+	const handleTabChange = (tab: TabType) => {
		setActiveTab(tab);
	};
apps/platform/.env.example (1)

49-54: Integration with new services.

The addition of PostHog analytics and custom IPFS gateway configuration expands the platform's capabilities. Consider adding comments in the env file explaining these services' purposes.

# PostHog settings
+# Used for analytics and user behavior tracking
NEXT_PUBLIC_POSTHOG_API_KEY=

# Custom grants stack indexer url
+# Used for retrieving grants data from a custom indexer instance
GRANTS_STACK_INDEXER_URL=
+# Gateway for accessing IPFS content
NEXT_PUBLIC_IPFS_GATEWAY_URL=
CONTRIBUTING.md (4)

19-27: Simplified setup instructions.

The development setup instructions are concise and use pnpm, matching the project's tooling. Consider adding instructions for environment variables setup.

2. Start the development server:
```bash
pnpm dev

+3. Environment setup:
+bash +# Copy the example environment file +cp apps/platform/.env.example apps/platform/.env.local +# Edit the environment variables as needed +


---

`38-46`: **Clear commit message conventions.**

The commit message guidelines follow conventional commits format, which is an industry standard practice.


Add a preposition to maintain grammatical consistency:

```diff
- Follow conventional commits format:
+ Follow the conventional commits format:
🧰 Tools
🪛 LanguageTool

[uncategorized] ~39-~39: Possible missing preposition found.
Context: ...se clear, descriptive commit messages - Follow conventional commits format: - `feat:...

(AI_HYDRA_LEO_MISSING_TO)


48-54: Well-structured PR process.

The pull request process is well defined with logical steps. Step 4 has a minor grammatical issue.

3. Update documentation if needed
-4. Create a pull request with a clear description of changes
+4. Create a pull request with a clear description of the changes
5. Link any related issues
🧰 Tools
🪛 LanguageTool

[grammar] ~52-~52: Did you mean “to Create”?
Context: ...ly 3. Update documentation if needed 4. Create a pull request with a clear description...

(MISSING_TO_BEFORE_A_VERB)


69-71: Translation contribution guidance.

Providing specific guidance for translators is valuable. Consider adding more detail on the translation workflow.

## 🌍 Translations

-We welcome contributions to improve our Croatian translations or add new languages. Please contact the maintainers before starting significant translation work.
+We welcome contributions to improve our Croatian translations or add new languages. Translation files are located in the `apps/platform/messages/` directory. Please contact the maintainers before starting significant translation work to ensure coordination.
packages/kit/src/hooks/useApplications.ts (1)

6-6: Remove unused imports if not needed.

The import statement includes ApplicationInput, which is not referenced within this file. If it's no longer needed here, consider removing it to keep imports concise.

apps/platform/src/app/projects/propose/actions.ts (1)

163-193: Reuse email content logic to avoid duplication.

The admin email is almost identical to the end-user email in structure. Consider refactoring shared pieces (like file URL handling, content blocks, or repeated translations) into a helper function to avoid duplication and ease maintenance.

apps/platform/src/app/components/project/ProjectSidebar.tsx (3)

20-20: Extract magic number into a constant.

28.6 might be unclear to future maintainers. Consider pulling this value into a named constant or config to clarify its origin and facilitate adjustments.

- const estimatedMatch = Math.round(donationAmount * 28.6);
+ const MATCH_MULTIPLIER = 28.6;
+ const estimatedMatch = Math.round(donationAmount * MATCH_MULTIPLIER);

71-80: Inline currency symbol improves user experience.

Prepending the Euro sign is a handy UI enhancement. Consider using Intl.NumberFormat for i18n currency support if multiple regions or currencies are needed.


87-87: Consistent currency display.

Showing estimatedMatch with "€" at the input is user-friendly. Just as with donation amount, consider format localization for a more robust approach.

apps/platform/src/app/projects/propose/page.tsx (1)

196-198: Consider adding loading state for form submission

While the form handles success state well, there's no visual indication to users that form submission is in progress.

Consider adding a loading state when the form is being submitted:

-const [isLoaded, setIsLoaded] = useState(false);
+const [isLoaded, setIsLoaded] = useState(false);
+const [isSubmitting, setIsSubmitting] = useState(false);

// Modify formAction to use wrapper function
-const [state, formAction] = useFormState(createProjectAction, {
+const [state, formActionOriginal] = useFormState(createProjectAction, {
  message: [],
  status: false,
});

+const formAction = async (formData: FormData) => {
+  setIsSubmitting(true);
+  try {
+    await formActionOriginal(formData);
+  } finally {
+    setIsSubmitting(false);
+  }
+};

// In the submit button, show loading state
// <ProjectProposalFormButton isLoading={isSubmitting} />

Also applies to: 155-155

apps/platform/src/app/components/project/ProjectDetails.tsx (6)

20-20: Check fallback for environment variable
Currently, the boolean is derived by strict equality to "true". If NEXT_PUBLIC_USE_DUMMY_DATA is not defined, the code defaults to false. This is safe, but consider logging or handling scenarios where the variable is missing.


35-42: Fallback selection for missing dummy data
Returning the first dummy application if none is found is fine for development. However, consider providing clearer error handling or logging to aid debugging if an invalid ID is passed.


50-59: Handle loading and error states
If useApplicationById triggers an asynchronous request, consider adding explicit handling for loading or error states to improve user experience.


66-72: No application found fallback
The user-friendly message is a good approach. Consider adding a link or redirect option to guide users when no data is present.


74-74: Unnecessary optional chaining
At this point, the application is verified to be non-undefined, so optional chaining is redundant. Consider removing it.

- let progressColor = getProjectProgressBGColor(application?.fundedPercentage);
+ let progressColor = getProjectProgressBGColor(application.fundedPercentage);

86-86: Fallback banner image
Providing a default URL ensures a proper image is always rendered. Consider verifying whether application.bannerUrl is valid or returns 404 in production.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dcd3595 and 435f2d4.

⛔ Files ignored due to path filters (3)
  • apps/platform/public/images/icons/icon-lang-gray.svg is excluded by !**/*.svg
  • apps/platform/public/images/icons/icon-lang.svg is excluded by !**/*.svg
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (65)
  • .gitignore (1 hunks)
  • CONTRIBUTING.md (1 hunks)
  • FUNDING.json (1 hunks)
  • README.md (1 hunks)
  • apps/platform/.env.example (3 hunks)
  • apps/platform/messages/en.json (1 hunks)
  • apps/platform/messages/hr.json (1 hunks)
  • apps/platform/next.config.mjs (2 hunks)
  • apps/platform/src/app/Header.tsx (1 hunks)
  • apps/platform/src/app/[chainId]/page.tsx (0 hunks)
  • apps/platform/src/app/[chainId]/rounds/[roundId]/apply/page.tsx (0 hunks)
  • apps/platform/src/app/[chainId]/rounds/[roundId]/fund/page.tsx (0 hunks)
  • apps/platform/src/app/[chainId]/rounds/[roundId]/page.tsx (0 hunks)
  • apps/platform/src/app/components/LanguageSwitcher.tsx (2 hunks)
  • apps/platform/src/app/components/Navigation.tsx (1 hunks)
  • apps/platform/src/app/components/RoundPhase.tsx (1 hunks)
  • apps/platform/src/app/components/cart/AddToCart.tsx (2 hunks)
  • apps/platform/src/app/components/cart/CartProjectCard.tsx (1 hunks)
  • apps/platform/src/app/components/common/Icons.tsx (1 hunks)
  • apps/platform/src/app/components/common/Socials.tsx (1 hunks)
  • apps/platform/src/app/components/footer/Footer.tsx (1 hunks)
  • apps/platform/src/app/components/footer/FooterLinks.tsx (1 hunks)
  • apps/platform/src/app/components/footer/FooterRoundId.tsx (1 hunks)
  • apps/platform/src/app/components/homepage/HomepageAbout.tsx (0 hunks)
  • apps/platform/src/app/components/homepage/HomepageIntro.tsx (1 hunks)
  • apps/platform/src/app/components/project/ProjectCard.tsx (1 hunks)
  • apps/platform/src/app/components/project/ProjectDetails.tsx (2 hunks)
  • apps/platform/src/app/components/project/ProjectSidebar.tsx (3 hunks)
  • apps/platform/src/app/components/project/ProjectSocialIcons.tsx (1 hunks)
  • apps/platform/src/app/components/projects/NeighborhoodSelector.tsx (2 hunks)
  • apps/platform/src/app/components/projects/ProjectList.tsx (1 hunks)
  • apps/platform/src/app/components/projects/ProjectListHeader.tsx (1 hunks)
  • apps/platform/src/app/components/projects/ProjectListMap.tsx (1 hunks)
  • apps/platform/src/app/config/index.ts (1 hunks)
  • apps/platform/src/app/contexts/roundIdContext.tsx (1 hunks)
  • apps/platform/src/app/helpers/discourseHelpers.ts (2 hunks)
  • apps/platform/src/app/helpers/projectHelper.ts (1 hunks)
  • apps/platform/src/app/hooks/useFileHandler.ts (1 hunks)
  • apps/platform/src/app/layout.tsx (1 hunks)
  • apps/platform/src/app/projects/page.tsx (1 hunks)
  • apps/platform/src/app/projects/propose/actions.ts (4 hunks)
  • apps/platform/src/app/projects/propose/page.tsx (18 hunks)
  • apps/platform/src/app/providers.tsx (2 hunks)
  • apps/platform/src/data/sample_content/applications.json (1 hunks)
  • apps/platform/tailwind.config.ts (2 hunks)
  • packages/kit/package.json (1 hunks)
  • packages/kit/src/api/provider.tsx (1 hunks)
  • packages/kit/src/api/providers/grants-stack/index.ts (3 hunks)
  • packages/kit/src/api/providers/grants-stack/utils.ts (2 hunks)
  • packages/kit/src/api/types.d.ts (1 hunks)
  • packages/kit/src/applications/card.tsx (1 hunks)
  • packages/kit/src/config/chains.ts (1 hunks)
  • packages/kit/src/config/cometh.ts (3 hunks)
  • packages/kit/src/hooks/useApplications.ts (1 hunks)
  • packages/kit/src/hooks/useDebounce.ts (1 hunks)
  • packages/kit/src/index.tsx (1 hunks)
  • packages/kit/src/rounds/create.tsx (1 hunks)
  • packages/kit/src/rounds/donate.tsx (1 hunks)
  • packages/kit/src/rounds/fund.tsx (1 hunks)
  • packages/kit/src/strategies/index.ts (2 hunks)
  • packages/kit/src/strategies/quadratic-funding/allocate.tsx (1 hunks)
  • packages/kit/src/strategies/quadratic-funding/qf.types.ts (1 hunks)
  • packages/kit/src/strategies/quadratic-funding/utils/getTokenMetadata.ts (1 hunks)
  • packages/kit/src/wagmi/providers/rainbow-kit.provider.tsx (1 hunks)
  • turbo.json (2 hunks)
💤 Files with no reviewable changes (5)
  • apps/platform/src/app/[chainId]/rounds/[roundId]/page.tsx
  • apps/platform/src/app/[chainId]/page.tsx
  • apps/platform/src/app/[chainId]/rounds/[roundId]/apply/page.tsx
  • apps/platform/src/app/components/homepage/HomepageAbout.tsx
  • apps/platform/src/app/[chainId]/rounds/[roundId]/fund/page.tsx
✅ Files skipped from review due to trivial changes (11)
  • apps/platform/src/app/components/RoundPhase.tsx
  • packages/kit/src/rounds/donate.tsx
  • packages/kit/src/config/chains.ts
  • packages/kit/src/rounds/create.tsx
  • packages/kit/src/rounds/fund.tsx
  • packages/kit/src/strategies/quadratic-funding/allocate.tsx
  • packages/kit/src/strategies/quadratic-funding/utils/getTokenMetadata.ts
  • apps/platform/src/app/components/homepage/HomepageIntro.tsx
  • FUNDING.json
  • packages/kit/src/applications/card.tsx
  • apps/platform/src/app/components/common/Socials.tsx
🧰 Additional context used
🪛 LanguageTool
CONTRIBUTING.md

[uncategorized] ~39-~39: Possible missing preposition found.
Context: ...se clear, descriptive commit messages - Follow conventional commits format: - `feat:...

(AI_HYDRA_LEO_MISSING_TO)


[grammar] ~52-~52: Did you mean “to Create”?
Context: ...ly 3. Update documentation if needed 4. Create a pull request with a clear description...

(MISSING_TO_BEFORE_A_VERB)

🔇 Additional comments (101)
.gitignore (1)

44-45: Entry Addition: storybook-static
The addition of the storybook-static line effectively ignores the Storybook build output, which prevents these generated files from being tracked by git. This aligns with best practices for managing build outputs and supports the related environment variable configurations.

packages/kit/src/strategies/quadratic-funding/qf.types.ts (1)

23-23: Addition of neighborhood property looks good

The neighborhood property has been added to the FundedApplication type, which appropriately extends the base Application type. This addition aligns with the project's new neighborhood filtering functionality mentioned in the PR summary.

packages/kit/src/api/types.d.ts (1)

185-185: Optional websiteUrl property is well-defined

Adding the optional websiteUrl property to the Application type is a good enhancement that maintains backward compatibility while allowing for website references in application data.

packages/kit/src/index.tsx (1)

41-41: Export of useDebounce hook looks good

Adding the export statement for the useDebounce hook follows the existing pattern in the file and makes the hook available to other components in the application.

apps/platform/src/app/components/common/Icons.tsx (1)

36-37: New globe icons added properly.

The new globe icons follow the established naming convention and path structure. They appropriately support the language switcher functionality as referenced in the AI summary.

apps/platform/src/app/components/footer/FooterLinks.tsx (1)

13-13: Improved responsive design implementation.

The class changes convert the footer links from a fixed horizontal layout to a responsive design that displays as a column on mobile and as a row on medium and larger screens. The gap adjustments (smaller on mobile, larger on desktop) are also appropriate for the different layouts.

packages/kit/src/wagmi/providers/rainbow-kit.provider.tsx (1)

4-4:

❓ Verification inconclusive

Package dependency source updated.

The import has been changed from @gitcoin/gitcoin-chain-data to @b0rza/gitcoin-chain-data. This matches the package.json dependency change and ensures consistency across the codebase.


🏁 Script executed:

#!/bin/bash
# Check if the new package is being consistently used across the codebase
echo "Checking for any remaining references to @gitcoin/gitcoin-chain-data..."
rg "@gitcoin/gitcoin-chain-data" --type ts --type tsx

echo "Confirming all references now use @b0rza/gitcoin-chain-data..."
rg "@b0rza/gitcoin-chain-data" --type ts --type tsx

Length of output: 449


Manual Verification Required: Review Dependency Reference Update

The initial shell script produced errors due to the unrecognized file type tsx. To ensure that all references have been updated correctly across the codebase, please re-run the verification using the updated shell script below:

#!/bin/bash
echo "Searching for '@gitcoin/gitcoin-chain-data' in TypeScript and TSX files..."
rg "@gitcoin/gitcoin-chain-data" --glob "*.ts" --glob "*.tsx"

echo "Searching for '@b0rza/gitcoin-chain-data' in TypeScript and TSX files..."
rg "@b0rza/gitcoin-chain-data" --glob "*.ts" --glob "*.tsx"
  • Ensure that the first command returns no results.
  • Confirm that all references now correctly use @b0rza/gitcoin-chain-data.

Please verify these results manually once the script is executed.

packages/kit/package.json (1)

54-54:

✅ Verification successful

Package dependency updated.

The Gitcoin chain data package has been switched from @gitcoin/gitcoin-chain-data to @b0rza/gitcoin-chain-data with a specific version (1.1.2). This aligns with the import changes in the codebase.


🏁 Script executed:

#!/bin/bash
# Check if the package exists and get information about it
echo "Checking package information for @b0rza/gitcoin-chain-data..."
npm view @b0rza/gitcoin-chain-data version description homepage

Length of output: 351


Dependency update verified.

The dependency in packages/kit/package.json now correctly references "@b0rza/gitcoin-chain-data": "1.1.2". The npm view output confirms that the package is at version 1.1.2 and details (description and homepage) match expectations. This aligns with the updated import changes in the codebase, so no further modifications are required.

apps/platform/src/app/components/Navigation.tsx (1)

33-44: Feature flag implementation looks good.

The conditional rendering for the projects page navigation link is well implemented. Using the environment variable as a feature flag is a clean approach, and the styling maintains consistency with other navigation links.

apps/platform/src/app/layout.tsx (2)

35-35: Layout improvement for full-height design.

Adding flex flex-col min-h-screen to the body creates a proper layout foundation that ensures content spans the full viewport height.


43-43: Good use of flex-grow for content spacing.

The flex-grow class on the main element ensures that the content area expands to fill available space, which pairs well with the flex container setup on the body element.

packages/kit/src/hooks/useDebounce.ts (1)

1-17: Well-implemented debounce hook.

This is a clean, efficient implementation of a debounce hook that follows React best practices:

  • Generic typing allows reuse with any value type
  • Proper cleanup in the useEffect return function prevents memory leaks
  • Appropriate dependency array ensures the effect runs when necessary
  • Default delay value provides sensible out-of-the-box functionality

The hook will be useful for improving performance in search inputs, form fields, and other scenarios where debouncing is needed.

packages/kit/src/api/provider.tsx (1)

25-29:

✅ Verification successful

Environment-based PostHog configuration.

Good change to use environment variables for PostHog initialization. This improves configurability and follows best practices for managing API keys across different environments.


🏁 Script executed:

#!/bin/bash
# Check if the environment variable is properly defined in .env.example
grep -l "NEXT_PUBLIC_POSTHOG_API_KEY" $(find . -name ".env.example")

Length of output: 124


PostHog Environment Configuration Verified

The use of the NEXT_PUBLIC_POSTHOG_API_KEY environment variable in the PostHog initialization is correctly implemented, and our check confirms that it is defined in ./apps/platform/.env.example. No further changes are needed.

apps/platform/src/app/providers.tsx (3)

5-5: New context provider introduced.

The import of RoundIdProvider indicates a new context for managing round IDs throughout the application.


22-27: Improved code organization.

Extracting the API configuration into a separate variable improves readability and maintainability.


29-33: Proper provider nesting and structure.

The RoundIdProvider has been correctly positioned to wrap the ComethProvider, ensuring round ID context is available where needed.

apps/platform/src/app/components/project/ProjectCard.tsx (2)

39-39: Dynamic project routing implemented.

The Link href has been updated from a hardcoded value to a dynamic path based on the application ID, improving routing and reusability.


42-42: Dynamic content display.

Replacing the hardcoded project name with dynamic application name ensures the component displays correct contextual information.

apps/platform/src/app/components/LanguageSwitcher.tsx (3)

31-33: Enhanced visual indication for language selection.

Adding a conditional globe icon based on screen type improves the user interface with appropriate visual cues.


47-47: Improved dropdown width consistency.

Changing from 'w-30' to 'w-full' ensures a consistent width for the language dropdown on non-mobile screens.


52-58: Added visual icon for better UX.

The globe icon addition enhances user experience by providing a clear visual indicator for language selection functionality.

apps/platform/src/app/components/cart/AddToCart.tsx (2)

34-35: Enhanced button interaction feedback.

Adding active:scale-75 transition-transform classes improves user experience by providing visual feedback when the button is clicked.


46-46: Improved active state visual indication.

The active:bg-green/90 class enhances user feedback by slightly changing the background color during interaction.

apps/platform/src/app/helpers/projectHelper.ts (1)

39-40: Good enhancement: Adding a default value improves function robustness

Making the progress parameter optional with a default value of 0 is a good practice. This change ensures the function will always return a valid CSS class even when called without arguments, making the code more defensive.

apps/platform/src/app/components/project/ProjectSocialIcons.tsx (3)

7-15: Improved social sharing implementation with dynamic URL construction

The change from accepting a full URL to just requiring a project ID is a good architectural improvement. By constructing the sharing URL dynamically using the environment variable NEXT_PUBLIC_URL, you've made the component more maintainable and ensured consistent URL patterns across the application.

The proper URL encoding of both the URL and title parameters ensures the shared links will be correctly formatted for social media platforms.


16-19: LGTM - Facebook sharing implementation updated correctly

The Facebook sharing function now properly uses the dynamically constructed shareableUrl.


21-24: LGTM - Twitter sharing implementation enhanced

The Twitter sharing function now correctly uses both the dynamically constructed shareableUrl and the encoded shareableTitle, providing a better sharing experience for users.

apps/platform/src/app/components/footer/Footer.tsx (1)

4-12: Well-implemented feature flag for round ID input

Good implementation of the conditional FooterRoundId component using the NEXT_PUBLIC_ALLOW_ROUND_INPUT environment variable as a feature flag. This approach allows for easy enabling/disabling of this feature across different environments.

The layout changes with flex-col-reverse and responsive adjustments improve the footer's mobile and desktop appearance.

apps/platform/src/app/components/projects/ProjectListMap.tsx (1)

62-67: Replace hardcoded coordinate data with dynamic values

The TODO comment indicates this is temporary data. In a production environment, you should replace this with real coordinates from your applications or a geocoding service.

Consider implementing a solution to generate coordinates from address data or store coordinates with each application to avoid this mapping problem entirely.

apps/platform/src/app/Header.tsx (4)

47-47: UI spacing adjustment for consistency.

The margin of the MuqaConnectButton has been reduced from mx-4 to mx-2, which creates a more compact header design.


49-51: Repositioned LanguageSwitcher component for better layout.

Moving the LanguageSwitcher to its own container with appropriate margins improves the overall organization of the header elements.


54-54: Consistent margin reduction for header elements.

Reducing the margin from mx-4 to mx-2 for this link maintains consistency with other header components.


61-64: Enhanced cart button with animation feedback.

Good improvement adding the animation when items are in the cart, providing visual feedback to the user. The key prop ensures proper re-rendering when the cart count changes.

packages/kit/src/api/providers/grants-stack/utils.ts (2)

3-4: Improved configurability with environment variable.

Using an environment variable for the IPFS gateway URL with a sensible default improves flexibility across different environments.


5-8: Enhanced IPFS gateway URL generation with optional parameters.

The updated function signature with optional type parameter provides more flexibility, and the implementation correctly handles the URL construction with or without the parameter.

apps/platform/next.config.mjs (2)

9-12: Dynamic IPFS image configuration based on environment.

The implementation correctly parses the IPFS gateway URL to extract protocol and hostname for Next.js image optimization.


37-37: Applied dynamic IPFS configuration to remotePatterns.

Spreading the ipfsImageConfig into remotePatterns is an elegant way to conditionally include the IPFS gateway in the Next.js image configuration.

apps/platform/src/app/components/projects/NeighborhoodSelector.tsx (2)

10-12: Well-defined props type for the component.

Clear type definition for the component props improves code readability and type safety.


14-14: Renamed component with proper props handling.

The component name change from ProjectsSidebar to NeighborhoodSelector better reflects its purpose, and it now accepts props for more reusability.

apps/platform/src/app/components/cart/CartProjectCard.tsx (1)

74-82: Improved currency input field implementation

The changes enhance the user experience by visually separating the currency symbol from the numeric input while maintaining the same functionality. This follows best practices for currency input fields.

apps/platform/src/app/config/index.ts (3)

10-10: Good addition of forum discussion link

The new forum discussion link provides a useful resource for users to engage with the community.


13-13: Approved GitHub repository URL update

Updated GitHub link to point to the correct zazelenimo repository instead of the demo repository.


3-3:

❓ Verification inconclusive

Verify URL path construction after removing leading slash

The removal of the leading slash from CodaFormProjectLink might affect how this path is used throughout the application. Ensure that all components using this constant properly construct URLs with this path.


🏁 Script executed:

#!/bin/bash
# Check how CodaFormProjectLink is used in the codebase
rg -A 3 -B 3 "CodaFormProjectLink" --type ts --type tsx

Length of output: 83


Action: Perform Manual Verification of URL Construction

It appears that our initial search for usages of CodaFormProjectLink failed due to the tsx file type not being recognized. Please verify that all components using this constant correctly construct URLs (restoring the necessary leading slash when needed) by running a revised search. For example, try this updated command to account for both TypeScript and TSX files:

#!/bin/bash
# Re-check usage of CodaFormProjectLink in .ts and .tsx files using glob patterns
rg -A 3 -B 3 "CodaFormProjectLink" --glob "*.ts" --glob "*.tsx"

Key points for manual review:

  • Verify URL Assembly: Ensure that any component that uses CodaFormProjectLink is correctly adding a leading slash (or handling the missing slash appropriately) when forming absolute URLs.
  • Confirm Across Files: Double-check through all relevant components that might rely on this constant to prevent unexpected URL construction issues.

Please re-run the revised search and inspect the usage contexts. Once confirmed that URL construction is handled correctly throughout the codebase, you can consider this verification complete.

apps/platform/src/app/components/projects/ProjectList.tsx (3)

1-1: Good implementation of neighborhood filtering

The addition of the neighborhood filtering functionality with proper state management enhances the user experience by allowing more targeted browsing of projects.

Also applies to: 5-6, 13-19


21-23: Well-implemented filtering logic with empty state handling

The filtering logic is clear and includes appropriate handling for when no applications match the selected filters.

Also applies to: 28-32


40-45: Commented-out pagination component

The pagination component is commented out rather than properly integrated with the filtered results. This suggests the feature might be incomplete.

Is the pagination intentionally disabled, or should it be integrated with the filtered results? Consider removing commented code if it's no longer needed or implementing a proper solution.

apps/platform/src/app/contexts/roundIdContext.tsx (1)

1-33: Well-structured context implementation for round ID management.

This implementation follows React's best practices for context creation and usage. The context provides both the roundId value and a setter function, while the custom hook includes proper error handling for when it's used outside the provider context.

A few observations:

  • Good use of environment variables for the default value
  • Clean separation of provider and hook functionality
  • Proper TypeScript typing for the context value and props
apps/platform/src/data/sample_content/applications.json (1)

1-142: Well-structured sample data for urban greening projects.

The JSON file provides comprehensive and consistent sample data for urban greening projects in Split. Each project has the same structure with appropriate fields for identification, description, status, and contribution tracking.

The descriptions are detailed and focus on the ecological benefits of each initiative, providing realistic content for development and testing.

apps/platform/tailwind.config.ts (2)

3-63: Good refactoring of color and animation definitions.

Moving color definitions into a separate object improves code organization and maintainability. The addition of keyframes and animation objects follows the same pattern, providing a consistent approach to theme configuration.

Each color includes a DEFAULT value and, where needed, a dark variant, which will simplify theme switching implementation.


75-77: Clean implementation of theme extension using the defined objects.

Using the named variables rather than inline objects improves readability and makes future modifications easier to manage.

apps/platform/messages/en.json (1)

2-236: Comprehensive localization implementation with clear sectioning.

The English localization file is well-structured with logical grouping of related text elements. The content is professional and appropriate for the application's focus on participatory budgeting for green urban projects.

Key sections include:

  • Home page content
  • Navigation items
  • Authentication messages
  • Project descriptions and statuses
  • Form labels and validation messages
  • FAQ content with detailed answers about the platform

The inclusion of placeholders like {seconds} and {amount} follows best practices for dynamic content insertion in localized strings.

packages/kit/src/api/providers/grants-stack/index.ts (2)

16-18: Good addition of configurable INDEXER_URL

The introduction of the INDEXER_URL constant with environment variable fallback improves configurability and makes the codebase more adaptable to different environments.


137-137:

❓ Verification inconclusive

Verify API response schema compatibility

The addition of the websiteUrl property to the application transformer is good for exposing more data. Make sure that any code relying on the application object structure is aware of this addition.


🏁 Script executed:

#!/bin/bash
# Description: Find all usages of application objects that might need to be updated to use the new websiteUrl property

# Find places where application objects are destructured
rg -t typescript -A 3 -B 3 "const \{.*\} = (app|application)"

# Find places where application.websiteUrl might already be referenced
rg -t typescript "application\.websiteUrl|app\.websiteUrl"

Length of output: 194


Attention: Verify API Schema Compatibility for websiteUrl Property

The inclusion of the websiteUrl field is a positive addition. However, the initial search script failed due to file type recognition issues. Please re-run or manually verify that every part of the code handling the application object—especially where it is destructured or referenced—is updated to consider the new property.

Recommendations:

  • Re-run verification with a revised shell script that filters by TypeScript file extensions. For example:
    #!/bin/bash
    # Check destructured application objects in .ts files
    rg -g "*.ts" -A 3 -B 3 "const \{.*\} = (app|application)"
    
    # Check for explicit references to websiteUrl in .ts files
    rg -g "*.ts" "application\.websiteUrl|app\.websiteUrl"
  • Manually inspect any usage that constructs or relies on the application object to ensure schema compatibility.
packages/kit/src/strategies/index.ts (2)

2-2:

❓ Verification inconclusive

Verify compatibility with the new dependency source

The import source for TContracts has been changed from @gitcoin/gitcoin-chain-data to @b0rza/gitcoin-chain-data. This could impact compatibility and introduce unexpected behaviors if the APIs differ.


🏁 Script executed:

#!/bin/bash
# Description: Check package versions and compatibility

# Check the version of the new package
npm list @b0rza/gitcoin-chain-data

# Check the structure of the TContracts type in both packages to ensure compatibility
echo "Checking if the repo contains the old package"
find . -name "node_modules/@gitcoin/gitcoin-chain-data" -type d

# If found, compare the TContracts type
find . -name "node_modules/@gitcoin/gitcoin-chain-data" -type d -exec cat {}/**/index.d.ts \; | grep -A 10 "TContracts"
find . -name "node_modules/@b0rza/gitcoin-chain-data" -type d -exec cat {}/**/index.d.ts \; | grep -A 10 "TContracts"

# Check if there are other imports using the old package
rg "@gitcoin/gitcoin-chain-data" --type ts

Length of output: 522


Action Required: Ensure Dependency Compatibility and API Consistency

The import for TContracts now comes from @b0rza/gitcoin-chain-data instead of the previous @gitcoin/gitcoin-chain-data. However, the verification script did not produce output for further comparison (e.g., no version or TContracts structure details were retrieved). This inconclusive result means that manual verification is required to ensure that:

  • The new dependency is correctly installed and available.
  • The TContracts API from the new package aligns with expectations and does not introduce unexpected behaviors.

Please confirm that the new package is properly integrated and that its API is compatible with its previous version. You might want to manually inspect the package or re-run targeted checks to compare the type definitions.


53-53:

❓ Verification inconclusive

Type expansion might require additional validation

The type of the compare function parameter has been expanded from [key: string, address: Address] to [key: string, address: Address | number]. This could lead to unexpected behaviors in code that assumes all addresses are of the Address type.

Ensure that any code handling these values can properly deal with both types:


🏁 Script executed:

#!/bin/bash
# Description: Check how the compare function is used throughout the codebase

# Find all places where reduceSupportedChains is called
rg "reduceSupportedChains" --type ts

# Check for places in the compare function where the address might be used in a way that's incompatible with numbers
rg -A 5 -B 5 "compare\(\[" --type ts

Length of output: 955


Attention: Validate Handling for Both Address and Number Types

After reviewing the usage of the compare function in reduceSupportedChains (see packages/kit/src/strategies/index.ts), the expanded parameter type [key: string, address: Address | number] does not show any immediate conflicts in how it’s being used. However, please ensure that:

  • The implementation of the compare function correctly distinguishes between an Address and a number.
  • Any logic that depends on chain.contracts values handles both value types appropriately, especially if operations assume address is always an Address.

If the compare function’s internals don’t yet account for number handling, consider adding additional type checks or conversion logic.

apps/platform/src/app/components/projects/ProjectListHeader.tsx (3)

6-8: Good addition of TypeScript interface.

The introduction of a properly typed interface for component props enhances type safety and code maintainability.


18-22: Clean prop reference update.

The useEffect dependency array has been properly updated to reference the new prop name, ensuring correct dependency tracking.


29-43: Improved markup organization.

Wrapping the controls in a dedicated div with a semantic class name improves structure and maintainability. The button styling is consistent with the application's design system.

apps/platform/.env.example (2)

1-1: Good addition of public URL variable.

Adding the base URL configuration is essential for properly generating absolute URLs in the application.


26-28: Support for Optimism Sepolia network added.

Good addition of configuration for Optimism Sepolia network, following the consistent pattern used for other networks.

apps/platform/messages/hr.json (3)

1-237: Comprehensive Croatian localization.

The translation file provides complete Croatian localization for the application. The keys are well-structured and organized by functional area.


115-115: Useful empty state message.

Adding a localized message for empty project listings improves user experience when filter criteria yield no results.


68-71: Clear explanation of quadratic funding.

The explanation of "kvadratno financiranje" (quadratic funding) is clear and helps users understand this novel voting mechanism.

CONTRIBUTING.md (2)

1-4: Clear introduction for contributors.

The welcoming introduction effectively explains the project's purpose and sets a positive tone for contributors.


75-76:

❓ Verification inconclusive

Missing documentation link.

The documentation link appears to be a placeholder. Update it to the actual documentation URL.


🏁 Script executed:

#!/bin/bash
# Check if the documentation URL exists in other files
rg -i "docs\.zazelenimo\.com" --type md

Length of output: 220


Documentation URL Verification:
The URL https://docs.zazelenimo.com/ is used consistently in both CONTRIBUTING.md (lines 75–76) and README.md. Please confirm that this is indeed the finalized documentation URL. If it is just a placeholder, update it accordingly.

packages/kit/src/hooks/useApplications.ts (3)

14-16: Nice use of generics for typed transformations.

Defining <T extends Application> and passing a transformer function enhances flexibility. Just ensure function calls across the codebase are updated to consistently supply the correct transformer if needed.

Also applies to: 21-21


25-26: No changes or code present on line 26.

There is no code on line 26, so no further action is needed here.


27-30: Handle potential undefined transformations gracefully.

When the API returns null or an empty object, this hook returns undefined. This is correct, but ensure downstream calls properly check for undefined when consuming the transformed data. Also confirm that T always extends Application, since the code uses transformer(application).

Also applies to: 35-35

apps/platform/src/app/projects/propose/actions.ts (4)

3-3: New config imports look good.

Importing ForumLink and ForumLinkDiscussion from config is consistent with usage throughout the file.


26-26: Robust fallback for string extraction.

Using ?.toString().trim() ?? '' prevents null or undefined issues. Good approach for form parsing.


96-96: Ensuring project data is included.

Listing project in topicData is essential for the proposal topic title. Looks good.


123-123: Topic link construction appears correct.

String interpolation for topic_slug and topic_id is fine. Just ensure the data is validated or trusted to avoid malformed URLs.

apps/platform/src/app/components/project/ProjectSidebar.tsx (2)

11-15: Destructuring props for clarity.

Accepting application: FundedApplication simplifies the component interface. Looks good; ensures typed usage throughout.


47-47: Translation usage looks good.

Using t('funded', { amount: application.targetAmount }) clearly communicates the target amount to the user.

apps/platform/src/app/helpers/discourseHelpers.ts (3)

130-147: Documentation improvement looks good

The updated JSDoc documentation clearly explains the purpose of the function, the parameters it accepts, and what it returns. The detailed explanation of each parameter and the function's behavior provides good context for developers.


148-162: Parameter addition is well implemented

The addition of the project parameter to the function signature is properly reflected in both the TypeScript interface and the function parameters. This change maintains type safety while extending functionality.


173-201: Improved structured content format

The new Markdown structure provides better organization with clear sections for Status, Content, and project details. The spoiler tag is a nice addition for forum readability. The call-to-action for forum registration is a good user engagement feature.

README.md (1)

1-61: Comprehensive README upgrade

The README has been significantly improved with detailed information about:

  • Project purpose and context
  • Current implementation details
  • Features list
  • Technology stack
  • Installation instructions
  • Contributing guidelines
  • Documentation links
  • Community information

This enhancement provides much better guidance for new contributors and users of the platform.

packages/kit/src/config/cometh.ts (4)

3-3: Import updated correctly for optimismSepolia

The import statement has been properly updated to include optimismSepolia from 'viem/chains'.


6-6: SupportedNetworks destructuring updated correctly

The destructuring of SupportedNetworks now includes OPTIMISM_SEPOLIA, which aligns with the new network support.


24-24: Type definition properly extended

The chainType type definition has been correctly updated to include 'OPTIMISM_SEPOLIA' as a possible value.


49-55:

✅ Verification successful

New network configuration follows established pattern

The configuration for OPTIMISM_SEPOLIA network follows the same structure as other networks, with proper environment variable references for API key and RPC URL.

Ensure that the corresponding environment variables are defined in your .env file:


🏁 Script executed:

#!/bin/bash
# Check if the required environment variables are defined in .env files
grep -r "NEXT_PUBLIC_OPTIMISM_SEPOLIA" --include="*.env*" .

Length of output: 262


Network configuration for OPTIMISM_SEPOLIA is correctly implemented and environment variables are in place.
The new network setup in packages/kit/src/config/cometh.ts follows the established pattern by referencing the proper environment variables for its API key and RPC. The verification script confirmed that both NEXT_PUBLIC_OPTIMISM_SEPOLIA_COMETH_API_KEY and NEXT_PUBLIC_OPTIMISM_SEPOLIA_TENDERLY_RPC are defined in the .env.example file located at ./apps/platform/.env.example.

No changes are necessary.

apps/platform/src/app/projects/propose/page.tsx (8)

14-14: Good use of custom hook for file handling

The useFileHandler hook abstracts file management functionality, improving code organization and reusability.


29-37: Well-structured initial form data object

The initialFormData object provides a clear template for the form's structure, making the component's state management more predictable.


44-50: Clean implementation of file handler hook

The destructuring of the hook's return values provides a clean interface for accessing file handling methods and state.


67-80: Form persistence with localStorage

Good implementation of localStorage for form data persistence, including proper error handling for JSON parsing failures.


83-90: Efficient localStorage update pattern

The second useEffect efficiently updates localStorage only after the initial load, preventing unnecessary writes.


93-105: Generic input handler improves maintainability

The generic input handler efficiently handles different input types including checkboxes, reducing code duplication and improving maintainability.


108-128: Enhanced user feedback during form submission

The countdown timer and redirection logic provide better feedback to users after form submission. The cleanup of localStorage and timers on component unmount prevents memory leaks.


136-143: Improved success UI with countdown link

The addition of a Link component with countdown timer provides a clear path forward for users after successful submission.

apps/platform/src/app/components/project/ProjectDetails.tsx (11)

1-1: Client-side Next.js directive enabled
No issues found.


10-14: Imports look consistent
These newly introduced imports appear necessary and correct. No issues found.


22-33: Potential random data mismatches
This function applies a random fundedPercentage. Repeated calls will yield different results, potentially causing inconsistent UI across re-renders. Also, the non-null assertion application.contributors?.amount! can lead to runtime errors if contributors is unexpectedly undefined. Consider adding fallback logic or checks.


44-48: Conditional data source
Choosing between dummy data and actual data here is straightforward and clear. No issues found.


64-64: Extracting the application
This usage of useResolvedApplication is consistent with the newly introduced hooks. No issues found.


77-77: Wrap container structure
No issues found. The structure and classNames appear to align with the desired layout.


79-79: Dynamic project name
No issues found. Displaying the project's name directly from the application data is correct.


93-93: Progress bar styling
Inline styling is sufficient here. No issues found.


98-98: Sidebar usage
Passing the application prop to ProjectSidebar correctly leverages the new hook. No issues found.


105-105: Verify user-provided content
If application.description is user-generated, ensure it is sanitized or validated to prevent XSS or other injection issues.


110-111: ProjectSocialIcons parameters
Passing id and title aligns well with the updated interface. No issues found.

Comment on lines +5 to +24
export default function Footer() {
const { roundId, setRoundId } = useRoundId();

function onRoundIdInput(e: any) {
const value = e.target.value.replace(/([^0-9]+)/gi, '');
setRoundId(value);
}

return (
<div className='relative'>
<span className='absolute left-2 top-1/2 -translate-y-1/2 text-sm text-gray-500'>ROUND</span>
<input
type="text"
className='text-sm px-2 py-2 pl-16 w-30 rounded-md border border-borderGray'
value={roundId}
onChange={onRoundIdInput}
/>
</div>
);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Component naming doesn't match file name and input event type needs improvement

The component is named Footer but exists in a file named FooterRoundId.tsx, which may cause confusion. Also, the event handler uses a non-specific any type.

Consider these improvements:

- export default function Footer() {
+ export default function FooterRoundId() {
  const { roundId, setRoundId } = useRoundId();

-  function onRoundIdInput(e: any) {
+  function onRoundIdInput(e: React.ChangeEvent<HTMLInputElement>) {
    const value = e.target.value.replace(/([^0-9]+)/gi, '');
    setRoundId(value);
  }
📝 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
export default function Footer() {
const { roundId, setRoundId } = useRoundId();
function onRoundIdInput(e: any) {
const value = e.target.value.replace(/([^0-9]+)/gi, '');
setRoundId(value);
}
return (
<div className='relative'>
<span className='absolute left-2 top-1/2 -translate-y-1/2 text-sm text-gray-500'>ROUND</span>
<input
type="text"
className='text-sm px-2 py-2 pl-16 w-30 rounded-md border border-borderGray'
value={roundId}
onChange={onRoundIdInput}
/>
</div>
);
}
export default function FooterRoundId() {
const { roundId, setRoundId } = useRoundId();
function onRoundIdInput(e: React.ChangeEvent<HTMLInputElement>) {
const value = e.target.value.replace(/([^0-9]+)/gi, '');
setRoundId(value);
}
return (
<div className='relative'>
<span className='absolute left-2 top-1/2 -translate-y-1/2 text-sm text-gray-500'>ROUND</span>
<input
type="text"
className='text-sm px-2 py-2 pl-16 w-30 rounded-md border border-borderGray'
value={roundId}
onChange={onRoundIdInput}
/>
</div>
);
}

Comment on lines +69 to 73
const markers: ApplicationWithCoords[] = applications.map((application, index) => ({
...application,
...coordinates[index]!,
icon: { url: getCustomPercentageMarkerIcon(application.fundedPercentage) },
}));
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improved marker generation but potential issue with coordinates mapping

The improvement to generate markers directly from applications is good, but there's a potential issue:

The code relies on the coordinates array index matching the applications index. If you have more applications than coordinates (currently only 3 hardcoded), this would cause runtime errors. The non-null assertion (!) assumes the coordinate always exists at that index.

Consider one of these solutions:

  1. Ensure coordinates array always has enough entries for all applications
  2. Add fallback coordinates when index is out of bounds:
- ...coordinates[index]!,
+ ...(coordinates[index] || { coords: { lat: 43.5081, lng: 16.4402 } }),
  1. For production, generate coordinates from actual application data rather than using the hardcoded array
📝 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
const markers: ApplicationWithCoords[] = applications.map((application, index) => ({
...application,
...coordinates[index]!,
icon: { url: getCustomPercentageMarkerIcon(application.fundedPercentage) },
}));
const markers: ApplicationWithCoords[] = applications.map((application, index) => ({
...application,
...(coordinates[index] || { coords: { lat: 43.5081, lng: 16.4402 } }),
icon: { url: getCustomPercentageMarkerIcon(application.fundedPercentage) },
}));

Comment on lines +31 to +33
useEffect(() => {
onChange(selectedNeighborhoods);
}, [selectedNeighborhoods]);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Missing dependency in useEffect.

The useEffect hook should include the onChange callback in its dependency array to prevent potential stale closure issues.

useEffect(() => {
    onChange(selectedNeighborhoods);
-}, [selectedNeighborhoods]);
+}, [selectedNeighborhoods, onChange]);
📝 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
useEffect(() => {
onChange(selectedNeighborhoods);
}, [selectedNeighborhoods]);
useEffect(() => {
onChange(selectedNeighborhoods);
}, [selectedNeighborhoods, onChange]);

Comment on lines +7 to +8
"NEXT_PUBLIC_URL",

Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Environment variables properly added to the build task

The new environment variables follow proper naming conventions with the NEXT_PUBLIC_ prefix for client-side variables and appear to support new features in the application.

Also applies to: 22-26, 31-33, 35-35, 37-37


🏁 Script executed:

#!/bin/bash
# Verify these environment variables are documented in .env.example
grep -E "NEXT_PUBLIC_(URL|OPTIMISM_SEPOLIA|INDEXER_URL|IPFS_GATEWAY_URL|ALLOW_ROUND_INPUT|USE_DUMMY_DATA|SHOW_PROJECTS_PAGE|POSTHOG_API_KEY)" .env.example

Length of output: 202


Action: Document Environment Variables in the .env.example File

  • The environment variables in turbo.json (lines 7-8) use the proper NEXT_PUBLIC_ prefix and are correctly added to the build task.
  • However, the verification script indicates that the expected .env.example file is missing from the repository.
  • Please add (or rename, if intended) a .env.example file to document all relevant public environment variables:
    • NEXT_PUBLIC_URL
    • NEXT_PUBLIC_OPTIMISM_SEPOLIA
    • NEXT_PUBLIC_INDEXER_URL
    • NEXT_PUBLIC_IPFS_GATEWAY_URL
    • NEXT_PUBLIC_ALLOW_ROUND_INPUT
    • NEXT_PUBLIC_USE_DUMMY_DATA
    • NEXT_PUBLIC_SHOW_PROJECTS_PAGE
    • NEXT_PUBLIC_POSTHOG_API_KEY
  • This change should also be applied to the environment variable listings at lines 22–26, 31–33, 35, and 37.

Comment on lines +1 to +58
import { useState, useRef } from 'react';

export type FileWithPreview = {
file: File;
url: string;
};

export default function useFileHandler() {
const [selectedFiles, setSelectedFiles] = useState<FileWithPreview[]>([]);
const inputRef = useRef<HTMLInputElement | null>(null);

// Handle file input change
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const files: File[] = event.target.files
? Array.from(event.target.files)
: [];

// Map files to include a preview URL
const filePreviews: FileWithPreview[] = files.map(file => ({
file,
url: URL.createObjectURL(file),
}));

setSelectedFiles(prevFiles => [...prevFiles, ...filePreviews]);
};

// Open file picker dialog
const openFilePicker = () => {
if (inputRef.current) {
inputRef.current.click();
}
};

// Remove file from selected files
const removeFile = (index: number) => {
const updatedFiles = selectedFiles.filter((_, i) => i !== index);
setSelectedFiles(updatedFiles);

// Create a new FileList based on updatedFiles
const dataTransfer = new DataTransfer();
updatedFiles.forEach(filePreview => {
dataTransfer.items.add(filePreview.file);
});

// Update the inputRef to reflect the new FileList
if (inputRef.current) {
inputRef.current.files = dataTransfer.files;
}
};

return {
selectedFiles,
handleFileChange,
openFilePicker,
removeFile,
inputRef,
};
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Memory leak risk in URL object management

The handleFileChange function creates object URLs with URL.createObjectURL() but never revokes them with URL.revokeObjectURL(). This can lead to memory leaks as these URLs will persist in memory even when they're no longer needed.

Consider adding a cleanup mechanism in a useEffect hook:

export default function useFileHandler() {
	const [selectedFiles, setSelectedFiles] = useState<FileWithPreview[]>([]);
	const inputRef = useRef<HTMLInputElement | null>(null);

+	// Clean up object URLs when component unmounts or when files change
+	useEffect(() => {
+		return () => {
+			selectedFiles.forEach((filePreview) => {
+				URL.revokeObjectURL(filePreview.url);
+			});
+		};
+	}, [selectedFiles]);

	// Rest of the code remains unchanged
}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +19 to +28
function extendApplicationData(applications: Application[]): FundedApplication[] {
const fundedPercentages = applications.map(() => Math.floor(Math.random() * 100));
return applications.map((app, index) => ({
...app,
neighborhood: neighborhoods[index]!,
fundedAmount: app.contributors?.amount!,
fundedPercentage: fundedPercentages[index]!,
targetAmount: (fundedPercentages[index]! / 100) * app.contributors?.amount!,
}));
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor random data generation into a conditional utility function

The current implementation of extendApplicationData always generates random percentages, even when used with real data. This could be confusing and lead to inconsistent UI.

Consider refactoring to make it clear when mock data is being generated:

-function extendApplicationData(applications: Application[]): FundedApplication[] {
-	const fundedPercentages = applications.map(() => Math.floor(Math.random() * 100));
-	return applications.map((app, index) => ({
-		...app,
-		neighborhood: neighborhoods[index]!,
-		fundedAmount: app.contributors?.amount!,
-	 	fundedPercentage: fundedPercentages[index]!,
-		targetAmount: (fundedPercentages[index]! / 100) * app.contributors?.amount!,
-	}));
-}
+function extendApplicationData(
+  applications: Application[], 
+  options: { useMockData?: boolean } = {}
+): FundedApplication[] {
+  return applications.map((app, index) => {
+    // Use actual data when available, or generate mock data when necessary
+    const fundedPercentage = options.useMockData 
+      ? Math.floor(Math.random() * 100)
+      : ((app.contributors?.amount || 0) / 100); // Calculate based on actual data if available
+    
+    return {
+      ...app,
+      neighborhood: app.metadata?.neighborhood || neighborhoods[index % neighborhoods.length]!,
+      fundedAmount: app.contributors?.amount || 0,
+      fundedPercentage,
+      targetAmount: (fundedPercentage / 100) * (app.contributors?.amount || 0),
+    };
+  });
+}

Then update the usage:

-	const { data, refetch, isError, error } = useApplications(query, extendApplicationData);
+	const { data, refetch, isError, error } = useApplications(query, 
+    (apps) => extendApplicationData(apps, { useMockData: false })
+  );

-	const extendedDummyApplications = extendApplicationData(dummyApplications as Application[]);
+	const extendedDummyApplications = extendApplicationData(
+    dummyApplications as Application[],
+    { useMockData: true }
+  );
📝 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
function extendApplicationData(applications: Application[]): FundedApplication[] {
const fundedPercentages = applications.map(() => Math.floor(Math.random() * 100));
return applications.map((app, index) => ({
...app,
neighborhood: neighborhoods[index]!,
fundedAmount: app.contributors?.amount!,
fundedPercentage: fundedPercentages[index]!,
targetAmount: (fundedPercentages[index]! / 100) * app.contributors?.amount!,
}));
}
function extendApplicationData(
applications: Application[],
options: { useMockData?: boolean } = {}
): FundedApplication[] {
return applications.map((app, index) => {
// Use actual data when available, or generate mock data when necessary
const fundedPercentage = options.useMockData
? Math.floor(Math.random() * 100)
: ((app.contributors?.amount || 0) / 100); // Calculate based on actual data if available
return {
...app,
neighborhood: app.metadata?.neighborhood || neighborhoods[index % neighborhoods.length]!,
fundedAmount: app.contributors?.amount || 0,
fundedPercentage,
targetAmount: (fundedPercentage / 100) * (app.contributors?.amount || 0),
};
});
}
// Update calls to extendApplicationData
const { data, refetch, isError, error } = useApplications(query,
(apps) => extendApplicationData(apps, { useMockData: false })
);
const extendedDummyApplications = extendApplicationData(
dummyApplications as Application[],
{ useMockData: true }
);

const t = useTranslations('projects');
const [activeTab, setActiveTab] = useState('board');

const allowRoundInput = process.env.NEXT_PUBLIC_ALLOW_ROUND_INPUT === 'true';
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

Verify that this environment variable is properly documented.

This feature flag controls conditional functionality. Ensure it's properly documented for other developers and in deployment guides.


🏁 Script executed:

#!/bin/bash
# Check if this environment variable is documented in README or other docs
rg -i "NEXT_PUBLIC_ALLOW_ROUND_INPUT" --type md

Length of output: 47


Documentation Update Required: The NEXT_PUBLIC_ALLOW_ROUND_INPUT flag isn’t currently referenced in our project documentation. Since a search across markdown files produced no results, please ensure that this feature flag’s purpose and usage are clearly added to the appropriate documentation and deployment guides (e.g., in the README, docs folder, or relevant internal documentation). This will help avoid any confusion for developers relying on this flag in the future.

Comment on lines +36 to +38
NEXT_PUBLIC_ALLOW_ROUND_INPUT=
NEXT_PUBLIC_USE_DUMMY_DATA=
NEXT_PUBLIC_SHOW_PROJECTS_PAGE=
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

New feature flags need documentation.

These feature flags control important application behavior. Ensure they're properly documented for other developers.


🏁 Script executed:

#!/bin/bash
# Check if these feature flags are documented in README or other docs
rg -i "(NEXT_PUBLIC_ALLOW_ROUND_INPUT|NEXT_PUBLIC_USE_DUMMY_DATA|NEXT_PUBLIC_SHOW_PROJECTS_PAGE)" --type md

Length of output: 109


Documentation required for new feature flags

The environment variables defined in apps/platform/.env.example (lines 36–38) are not referenced in our Markdown documentation. Since these flags control significant application behavior, please add detailed documentation—such as an entry in the README or a dedicated section in our docs folder—that explains their purpose, acceptable values, and any impact on the application.

  • NEXT_PUBLIC_ALLOW_ROUND_INPUT
  • NEXT_PUBLIC_USE_DUMMY_DATA
  • NEXT_PUBLIC_SHOW_PROJECTS_PAGE

Comment on lines +127 to +135
const messagePart10 = tMail.rich('messagePart10', {
link: chunks =>
`<a href='${topicLink}' target='_blank' class='underline hover:text-blue'>${project}</a>`,
`<a href='${ForumLinkDiscussion}' target='_blank' class='underline hover:text-blue'>${chunks}</a>`,
});

const images = fileUrls
.map(url => `<img src="${url}" alt="Image" />`)
.join('');

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Consider sanitizing user-supplied file URLs.

Generating <img src="${url}" /> tags from user inputs can lead to potential XSS or malicious link injection if url is unsafe. Ensure these are validated or sanitized, especially since they are placed in HTML content for emails.

+ // Example approach: validate that url is hosted on an allowed domain or follows a safe schema
// Then append only if valid

Committable suggestion skipped: line range outside the PR's diff.

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.

2 participants