Feature: Add campaign categories filter sidebar (#602) - #750
Conversation
- Add CategoryFilterSidebar component with category checkboxes - Sidebar collapses on mobile with toggle button - Active category filters shown as chips above campaign list - Category filter state synced with URL query params (?categories=) - OR logic for multiple category filters - Chips support individual filter removal - URL shareable with category filters
|
Someone is attempting to deploy a commit to the ritik4ever's projects Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughCampaignsTable adds URL-synchronized category filtering with responsive controls, removable chips, OR-based matching, and category-aware empty states. New Storybook components and stories, GitHub Pages deployment, commit validation, release settings, and Kilo configuration are also added. ChangesCampaign category filtering
Storybook components and publishing
Repository tooling and release configuration
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant CategoryFilterSidebar
participant CampaignsTable
participant campaignsTableUtils
User->>CategoryFilterSidebar: Toggle category
CategoryFilterSidebar->>CampaignsTable: onToggle(category)
CampaignsTable->>campaignsTableUtils: filterByCategories(campaigns, categoryFilters)
campaignsTableUtils-->>CampaignsTable: Filtered campaigns
CampaignsTable-->>User: Render filtered board and synchronized URL
Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (4)
frontend/src/index.css (2)
2058-2079: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
.chip-emphasisduplicates.chip.Only background/color/border differ; make it a modifier applied alongside
.chip(which the JSX already does:className="chip chip-emphasis").♻️ Proposed refactor
.chip-emphasis { background: rgba(99, 102, 241, 0.1); color: var(--primary-text); border: 1px solid rgba(99, 102, 241, 0.2); - padding: 6px 12px; - font-size: 0.75rem; - border-radius: 999px; - display: inline-flex; - align-items: center; - gap: 6px; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/index.css` around lines 2058 - 2079, Refactor the .chip-emphasis rule to contain only its differing background, color, and border declarations, relying on the existing .chip class for shared layout, spacing, typography, and shape styles; preserve the existing chip chip-emphasis JSX usage.
1951-1960: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsolidate the duplicate generic chip and board layout rules.
.chip,.chip-emphasis, and.chip-roware defined earlier at lines 1086/1562/1597, then redefined later at lines 2051+, and.board-layoutis defined again in the responsive rule at 2105. This order-dependent duplication makes the stylesheet fragile; merge the shared definitions so the intended board/category chip styles don’t silently override other markup.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/index.css` around lines 1951 - 1960, Consolidate the duplicate CSS definitions for .chip, .chip-emphasis, .chip-row, and .board-layout in index.css by merging shared properties into their existing primary rules and removing the later duplicate declarations, including the responsive .board-layout redefinition. Preserve the intended board/category-specific styles and responsive behavior without relying on source-order overrides.frontend/src/components/CampaignsTable.tsx (2)
376-390: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueExtract the repeated search-only condition.
hasSearchQuery && !hasAssetFilter && !hasStatusFilter && !hasCategoryFilterappears three times; a singleconst isSearchOnly = ...above the JSX keeps future filter axes from being missed in one of the three spots.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/components/CampaignsTable.tsx` around lines 376 - 390, Extract the repeated search-only expression into an isSearchOnly constant before the JSX, then use it for the EmptyState title, message, and action label conditions. Preserve the existing condition and handleClearFilters behavior.
161-176: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winPrefer writing
categoriesin the handlers instead of a state→URL effect.
handleStatusFilterChange(Lines 109-120) already sets state and the query param together. Here the effect pair means every mount issues areplacenavigation even when nothing changed, and a browser back that restores?categories=immediately gets replaced again. Moving thesetSearchParamscall intohandleCategoryToggle/handleCategoryClearand keeping only the URL→state effect matches the existing pattern and removes the round-trip.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/components/CampaignsTable.tsx` around lines 161 - 176, The categoryFilters state-to-URL effect causes unnecessary replace navigations and overrides browser history restoration. Remove that effect, keep the URL-to-state synchronization effect, and update handleCategoryToggle and handleCategoryClear to set categoryFilters and the categories query parameter together, matching the existing handleStatusFilterChange pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/components/CampaignsTable.tsx`:
- Around line 233-241: Update the filtering flow around applyFilters,
filterByCategories, and the asset/category controls so both selections do not
independently constrain the same assetCode field. Use a distinct category field
when category filtering is intended, or reconcile the controls as one shared
asset-selection axis while preserving the existing search and sorting behavior.
In `@frontend/src/components/CategoryFilterSidebar.tsx`:
- Around line 68-73: Fix the handler contract between CategoryFilterSidebar’s
CategoryItem and onToggle: adapt the checkbox’s boolean onChange callback so it
invokes onToggle with the associated category string, while preserving the
checked state behavior and ensuring CampaignsTable.handleCategoryToggle receives
the category rather than true/false.
- Around line 39-40: Update the state initialization and responsive behavior in
CategoryFilterSidebar so the filter starts closed when the media query resolves
to mobile, rather than relying on the initial false value. Keep isOpen
synchronized with isMobile when the breakpoint changes, including resize or
rotation across 767px, while preserving user-controlled open/closed state when
the viewport remains unchanged.
---
Nitpick comments:
In `@frontend/src/components/CampaignsTable.tsx`:
- Around line 376-390: Extract the repeated search-only expression into an
isSearchOnly constant before the JSX, then use it for the EmptyState title,
message, and action label conditions. Preserve the existing condition and
handleClearFilters behavior.
- Around line 161-176: The categoryFilters state-to-URL effect causes
unnecessary replace navigations and overrides browser history restoration.
Remove that effect, keep the URL-to-state synchronization effect, and update
handleCategoryToggle and handleCategoryClear to set categoryFilters and the
categories query parameter together, matching the existing
handleStatusFilterChange pattern.
In `@frontend/src/index.css`:
- Around line 2058-2079: Refactor the .chip-emphasis rule to contain only its
differing background, color, and border declarations, relying on the existing
.chip class for shared layout, spacing, typography, and shape styles; preserve
the existing chip chip-emphasis JSX usage.
- Around line 1951-1960: Consolidate the duplicate CSS definitions for .chip,
.chip-emphasis, .chip-row, and .board-layout in index.css by merging shared
properties into their existing primary rules and removing the later duplicate
declarations, including the responsive .board-layout redefinition. Preserve the
intended board/category-specific styles and responsive behavior without relying
on source-order overrides.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 46a51b3c-cb98-4318-b293-f031c4421a1f
📒 Files selected for processing (5)
.kilo/kilo.jsoncfrontend/src/components/CampaignsTable.tsxfrontend/src/components/CategoryFilterSidebar.tsxfrontend/src/components/campaignsTableUtils.tsfrontend/src/index.css
| const isMobile = useMediaQuery("(max-width: 767px)"); | ||
| const [isOpen, setIsOpen] = useState(!isMobile); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
isOpen never tracks isMobile.
useMediaQuery returns false on the first render (it resolves inside an effect), so isOpen always initializes to true and is never re-derived. On mobile the list renders expanded on load, and rotating/resizing across the 767px breakpoint leaves the state stale.
🔧 Proposed fix
-import { useState } from "react";
+import { useEffect, useState } from "react";
@@
const isMobile = useMediaQuery("(max-width: 767px)");
- const [isOpen, setIsOpen] = useState(!isMobile);
+ const [isOpen, setIsOpen] = useState(true);
+
+ useEffect(() => {
+ setIsOpen(!isMobile);
+ }, [isMobile]);📝 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.
| const isMobile = useMediaQuery("(max-width: 767px)"); | |
| const [isOpen, setIsOpen] = useState(!isMobile); | |
| const isMobile = useMediaQuery("(max-width: 767px)"); | |
| const [isOpen, setIsOpen] = useState(true); | |
| useEffect(() => { | |
| setIsOpen(!isMobile); | |
| }, [isMobile]); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/components/CategoryFilterSidebar.tsx` around lines 39 - 40,
Update the state initialization and responsive behavior in CategoryFilterSidebar
so the filter starts closed when the media query resolves to mobile, rather than
relying on the initial false value. Keep isOpen synchronized with isMobile when
the breakpoint changes, including resize or rotation across 767px, while
preserving user-controlled open/closed state when the viewport remains
unchanged.
|
@DanbabaJr Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
- add Storybook for component documentation - install @storybook/react-vite, @chromatic-com/storybook, and related addons - configure .storybook/main.ts for GitHub Pages base path - add stories for CampaignCard, ToastContainer, FundingProgress, Countdown, PledgeForm, ContributorList - add missing components: FundingProgress, Countdown, PledgeForm, ContributorList - add DesignTokens.doc story documenting CSS custom properties - add deploy-storybook.yml workflow to deploy to GitHub Pages - automate changelog via conventional commits - add @commitlint/cli and @commitlint/config-conventional - add .commitlintrc.json enforcing conventional commit types - add .husky/commit-msg hook to block non-conforming commits - update PR template with commit type selector - update release-please-config.json with breaking change keywords
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/PULL_REQUEST_TEMPLATE.md:
- Line 16: Update the `docs` checklist label in the pull request template to use
the hyphenated wording “Documentation-only changes.”
In @.github/workflows/deploy-storybook.yml:
- Line 21: Update the actions/checkout@v4 step in the workflow to set
persist-credentials to false, while preserving the existing explicit
github_token used by peaceiris/actions-gh-pages.
- Around line 29-32: Update the Storybook deployment step using
peaceiris/actions-gh-pages so it uses the supported v4 action and publishes the
generated frontend/storybook-static directory instead of resolving publish_dir
from the repository root.
In `@frontend/package.json`:
- Line 14: Update the test-storybook script in package.json to invoke the
installed Vitest Storybook project, using the project-specific Vitest command
such as vitest --project=storybook. Do not leave it pointing to the unavailable
test-storybook runner.
In `@frontend/src/components/FundingProgress.tsx`:
- Around line 15-23: Update the token-progress condition in FundingProgress so
multiple accepted tokens render token bars only when balances were actually
provided; do not default tokenBalances to an object that makes the check always
truthy. Preserve the percentFunded overall-progress fallback when tokenBalances
is absent.
In `@frontend/src/components/PledgeForm.tsx`:
- Line 27: Update PledgeForm’s acceptedTokens initialization to fall back to
campaign.acceptedTokens when the prop is omitted, then use that resolved list
for selected-token derivation and token-option rendering. Preserve
campaign.assetCode behavior only when neither source provides accepted tokens.
- Around line 82-91: Update the claim button handler in PledgeForm’s onClaim
flow to await the returned promise and catch rejected claim requests. Surface
the caught error through the component’s existing claim-error feedback
mechanism, while preserving the current campaign argument and button behavior.
- Line 1: Update the imports in PledgeForm so useState is imported as a runtime
value rather than through the type-only import, while keeping FormEvent
type-only. Ensure the component’s direct useState call resolves at runtime.
In `@release-please-config.json`:
- Around line 31-32: Remove the unsupported breaking-change-keywords property
from the release-please configuration, leaving the surrounding configuration and
official schema-compatible options unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: c0145508-d590-43cd-8210-1f75e7813b14
📒 Files selected for processing (18)
.commitlintrc.json.github/PULL_REQUEST_TEMPLATE.md.github/workflows/deploy-storybook.yml.gitignore.husky/commit-msgfrontend/.storybook/main.tsfrontend/package.jsonfrontend/src/components/ContributorList.stories.tsxfrontend/src/components/ContributorList.tsxfrontend/src/components/Countdown.stories.tsxfrontend/src/components/Countdown.tsxfrontend/src/components/DesignTokens.stories.tsxfrontend/src/components/FundingProgress.stories.tsxfrontend/src/components/FundingProgress.tsxfrontend/src/components/PledgeForm.stories.tsxfrontend/src/components/PledgeForm.tsxpackage.jsonrelease-please-config.json
| - uses: peaceiris/actions-gh-pages@v3 | ||
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| publish_dir: ./storybook-static |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workflow files =="
git ls-files '.github/workflows/*' || true
echo "== target workflow excerpt =="
if [ -f .github/workflows/deploy-storybook.yml ]; then
cat -n .github/workflows/deploy-storybook.yml
else
echo "target workflow not found"
fi
echo "== search for storybook-static usage and defaults/working-directory =="
rg -n "storybook-static|defaults:\s*run:\s*working-directory|working-directory:|uses: peaceiris/actions-gh-pages|build-storybook|storybook" -S .
echo "== git status/stat =="
git status --short || true
git diff --stat || trueRepository: ritik4ever/stellar-goal-vault
Length of output: 3787
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== frontend package scripts and config files =="
cat -n frontend/package.json
echo "== storybook config files =="
git ls-files frontend | rg '(^|/)(.storybook|storybook\.config|vite\.config|package\.json)$' || true
for f in frontend/.storybook/main.ts frontend/.storybook/main.js frontend/.storybook/main.cjs frontend/.storybook/main.mjs frontend/.storybook/preview.ts frontend/.storybook/preview.js frontend/.storybook/preview.cjs frontend/.storybook/preview.mjs frontend/vite.config.ts frontend/vite.config.js frontend/package.json; do
if [ -f "$f" ]; then
echo "--- $f"
cat -n "$f"
fi
done
echo "== action usage refs =="
rg -n "peaceiris/actions-gh-pages" .github/workflows packages.json package.json 2>/dev/null || trueRepository: ritik4ever/stellar-goal-vault
Length of output: 5773
🌐 Web query:
GitHub Actions workflow syntax defaults.run.working-directory apply only to run steps
💡 Result:
Yes, the GitHub Actions workflow syntax for defaults.run.working-directory applies exclusively to run steps [1][2][3]. According to official GitHub documentation, the defaults.run keyword is used to provide default shell and working-directory options specifically for all run steps within a workflow or a job [1][4][5]. This setting does not affect other types of steps, such as those that use uses to invoke actions [6]. Actions executed via uses manage their own execution environment and are not impacted by the defaults.run configuration [6]. To summarize the scope: - It applies to run steps (commands executed directly in the shell) [1][2]. - It does not apply to steps that utilize uses (actions) [6]. - You can set these defaults at the workflow level (under defaults:) or override them at the job level (under jobs.<job_id>.defaults:) [1][2][3]. Job-level settings take precedence over workflow-level settings [1][3].
Citations:
- 1: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax?use_case=
- 2: https://docs.github.com/en/enterprise-cloud@latest/actions/how-tos/write-workflows/choose-what-workflows-do/set-default-values-for-jobs
- 3: https://docs.github.com/en/enterprise-cloud@latest/actions/reference/workflows-and-actions/workflow-syntax
- 4: https://docs.github.com/en/enterprise-server@3.20/actions/how-tos/write-workflows/choose-what-workflows-do/set-default-values-for-jobs
- 5: https://docs.github.com/en/enterprise-server@3.21/actions/reference/workflows-and-actions/workflow-syntax
- 6: @actions/exec seems to ignore working-directory workflow setting actions/toolkit#841
🌐 Web query:
peaceiris actions-gh-pages v3 publish_dir working directory behavior
💡 Result:
In peaceiris/actions-gh-pages (including v3), the publish_dir option specifies the source directory within your repository that contains the static files you wish to deploy to the gh-pages branch [1][2]. The contents of this specified directory are copied to the root of the target branch (gh-pages by default) [1][3]. Key behaviors regarding publish_dir include: 1. Default Directory: If not specified, the action defaults to using a directory named public in the root of your repository [1][3]. 2. Path Resolution: The path provided to publish_dir is relative to the workspace root (GITHUB_WORKSPACE) [4][5]. 3. Repository Root Interaction: If you set publish_dir to. (the repository root), the action may inadvertently attempt to delete or modify the.git directory within the workspace, which can cause deployment failures [4]. It is generally recommended to use a dedicated subdirectory (e.g.,./dist or./public) for your build artifacts to avoid this [6]. 4. Cleanup Behavior: By default, the action removes existing files in the target branch before deploying the new contents from publish_dir [7]. You can use the keep_files option if you wish to preserve existing files in the target branch [8][7]. For complex setups where you need to deploy specific files or handle directories already present in the workspace, common practices include creating a dedicated build output directory or using a post-build step to copy all necessary assets into a single directory before calling the action [6][5].
Citations:
- 1: https://github.com/peaceiris/actions-gh-pages/blob/main/README.md
- 2: https://github.com/peaceiris/actions-gh-pages/tree/v3.8.0
- 3: https://github.com/peaceiris/actions-gh-pages
- 4: Not delete .git directory when publish_dir is GITHUB_WORKSPACE peaceiris/actions-gh-pages#548
- 5: Publish Jekyll locally generated main branch _site subdir to gh-pages branch for GitHub Pages User site? peaceiris/actions-gh-pages#596
- 6: How to add
dist/directory? peaceiris/actions-gh-pages#570 - 7: https://github.com/peaceiris/actions-gh-pages/releases/tag/v2.4.0
- 8: New Option destination_dir for deploying to a subdirectory peaceiris/actions-gh-pages#324
🌐 Web query:
peaceiris actions-gh-pages v4 README publish_dir
💡 Result:
In the peaceiris/actions-gh-pages version 4 GitHub Action, the publish_dir input specifies the source directory containing the static files you wish to deploy to GitHub Pages [1][2]. Key details regarding publish_dir include: - Function: It defines the directory from which the action will copy and deploy files [1][3]. - Default Value: The default directory is./public [1][2][4]. - Behavior: Only the contents of the specified directory are pushed to the target branch (which defaults to gh-pages) [1][3]. Example usage in a workflow file: - name: Deploy uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir:./public
Citations:
- 1: https://github.com/peaceiris/actions-gh-pages?tab=readme-ov-file
- 2: https://github.com/peaceiris/actions-gh-pages/blob/main/README.md
- 3: https://github.com/marketplace/actions/github-pages-action
- 4: https://github.com/peaceiris/actions-gh-pages
Publish the generated Storybook directory and use a supported deploy action.
defaults.run.working-directory only affects run steps, so peaceiris/actions-gh-pages receives ./storybook-static at the repository root. Storybook is configured to emit frontend/storybook-static, so update publish_dir and move to the supported v4 artifact.
Proposed fix
- - uses: peaceiris/actions-gh-pages@v3
+ - uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
- publish_dir: ./storybook-static
+ publish_dir: ./frontend/storybook-static📝 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.
| - uses: peaceiris/actions-gh-pages@v3 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ./storybook-static | |
| - uses: peaceiris/actions-gh-pages@v4 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ./frontend/storybook-static |
🧰 Tools
🪛 actionlint (1.7.12)
[error] 29-29: the runner of "peaceiris/actions-gh-pages@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/deploy-storybook.yml around lines 29 - 32, Update the
Storybook deployment step using peaceiris/actions-gh-pages so it uses the
supported v4 action and publishes the generated frontend/storybook-static
directory instead of resolving publish_dir from the repository root.
Source: Linters/SAST tools
| acceptedTokens = [], | ||
| tokenBalances = {}, | ||
| }: FundingProgressProps) { | ||
| return ( | ||
| <div className="campaign-progress"> | ||
| <div className="progress-copy"> | ||
| {pledgedAmount} / {targetAmount} {acceptedTokens.length > 1 ? 'Tokens' : assetCode} | ||
| </div> | ||
| {acceptedTokens.length > 1 && tokenBalances ? ( |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Preserve the overall-progress fallback when balances are absent.
Defaulting tokenBalances to {} makes the condition always truthy. A caller providing multiple accepted tokens without balances gets misleading zero-percent token bars instead of percentFunded.
Proposed fix
- tokenBalances = {},
+ tokenBalances,
...
- {acceptedTokens.length > 1 && tokenBalances ? (
+ {acceptedTokens.length > 1 && tokenBalances ? (📝 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.
| acceptedTokens = [], | |
| tokenBalances = {}, | |
| }: FundingProgressProps) { | |
| return ( | |
| <div className="campaign-progress"> | |
| <div className="progress-copy"> | |
| {pledgedAmount} / {targetAmount} {acceptedTokens.length > 1 ? 'Tokens' : assetCode} | |
| </div> | |
| {acceptedTokens.length > 1 && tokenBalances ? ( | |
| acceptedTokens = [], | |
| tokenBalances, | |
| }: FundingProgressProps) { | |
| return ( | |
| <div className="campaign-progress"> | |
| <div className="progress-copy"> | |
| {pledgedAmount} / {targetAmount} {acceptedTokens.length > 1 ? 'Tokens' : assetCode} | |
| </div> | |
| {acceptedTokens.length > 1 && tokenBalances ? ( |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/components/FundingProgress.tsx` around lines 15 - 23, Update the
token-progress condition in FundingProgress so multiple accepted tokens render
token bars only when balances were actually provided; do not default
tokenBalances to an object that makes the check always truthy. Preserve the
percentFunded overall-progress fallback when tokenBalances is absent.
| @@ -0,0 +1,107 @@ | |||
| import type { FormEvent, useState } from 'react'; | |||
There was a problem hiding this comment.
🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/sh
rg -n -P '^import\s+type\s+\{[^}]*\buseState\b' frontend/src/components/PledgeForm.tsx
rg -n '\buseState\s*\(' frontend/src/components/PledgeForm.tsxRepository: ritik4ever/stellar-goal-vault
Length of output: 313
🏁 Script executed:
#!/bin/sh
set -eu
printf '--- PledgeForm relevant section ---\n'
sed -n '1,120p' frontend/src/components/PledgeForm.tsx
printf '\n--- TypeScript config flags affecting import-namespace/type-only behavior ---\n'
find . -maxdepth 3 -path './frontend/**' -o -path './node_modules/**' -prune 2>/dev/null | grep -E '(^|/)(tsconfig.*\.json|package\.json)$' | while read -r f; do
if [ -f "$f" ]; then
sed -n '1,220p' "$f" | grep -n -E '"importsNotUsedAsValues"|"verbatimModuleSyntax"|"isolatedModules"|"noUnusedLocals"|"type":"module"|typeOnly|tsx|jsx' || true
fi
done
printf '\n--- React imports in nearby files ---\n'
rg -n "^import (?:type )?\\{[^\\n]*useState\\}" frontend/src -g '*.tsx' -g '*.ts' | head -50Repository: ritik4ever/stellar-goal-vault
Length of output: 258
🏁 Script executed:
#!/bin/sh
set -eu
printf '%s\n' '--- PledgeForm relevant section ---'
sed -n '1,120p' frontend/src/components/PledgeForm.tsx
printf '%s\n' ''
printf '%s\n' '--- TypeScript config flags affecting import behavior ---'
find . -maxdepth 3 \( -path './node_modules/*' -prune \) -o \( -type f \( -name 'tsconfig*.json' -o -name 'package.json' \) \) -print | sort | while read -r f; do
if [ -f "$f" ]; then
printf '%s\n' "--- $f ---"
sed -n '1,220p' "$f" | grep -n -Ei '"importsNotUsedAsValues"|"verbatimModuleSyntax"|"isolatedModules"|"noUnusedLocals"|"type":"module"|importsNotUsedAsValues|verbatimModuleSyntax|isolatedModules|noUnusedLocals|typeOnly|tsx|jsx' || true
fi
done
printf '%s\n' ''
printf '%s\n' '--- useState import usage in frontend source ---'
rg -n "^import (?:type )?\\{[^\\n]*useState\\}" frontend/src -g '*.tsx' -g '*.ts' | head -80 || true
printf '%s\n' ''
printf '%s\n' '--- runtime-state check if tsconfig exists ---'
if [ -f frontend/tsconfig.json ]; then cat frontend/tsconfig.json; fi
if [ -f tsconfig.json ]; then cat tsconfig.json; fiRepository: ritik4ever/stellar-goal-vault
Length of output: 5170
🌐 Web query:
TypeScript import type erases type imports used at runtime error TS2455
💡 Result:
The error TS2455, as described in your query, relates to the fundamental behavior of the import type syntax in TypeScript. It is important to clarify that import type is a compile-time-only construct guaranteed to be fully erased from the emitted JavaScript [1][2]. If you are encountering an error related to import type being "erased at runtime," it is likely because you are attempting to use an imported type as a value in your code [3][4]. Because import type declarations are completely removed during transpilation, the imported identifier does not exist in the generated JavaScript code [1][3]. Consequently, using it as a value (e.g., new MyType() or console.log(MyType)) is invalid and will trigger a TypeScript error [3][4]. To resolve this issue: 1. Check for Value Usage: Ensure that any identifier imported via import type is used only in type positions (e.g., in type annotations, implements clauses, or generic arguments) [1][2]. 2. Switch to Regular Imports: If you need to use the imported identifier as a value at runtime, you must use a standard import statement (e.g., import { MyValue } from './module') instead of import type [3][4]. 3. Module System Considerations: Note that using import or import type statements at the top level of a file will cause TypeScript to treat the file as a module [5][6]. If you are in a non-module environment or trying to mix ES modules and CommonJS, this can sometimes lead to module resolution errors [5][7]. In some specific cases where you need to reference a type without triggering module-level side effects or resolution issues, you can use the inline import() syntax: type MyType = import('./module').MyType; [5][6] If you believe you are seeing TS2455 specifically in a context that does not match this, please double-check the exact error message, as TS2455 is not a standard, commonly cited code for "import type erasure"; standard behavior for type-only imports is to simply be removed without error unless they are misused as values [3][2]. If the error persists, it may be a misconfiguration of your module resolution settings or a confusion with other module-related errors [5][7].
Citations:
- 1: https://www.typescriptlang.org/docs/handbook/modules/reference.html
- 2: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html
- 3: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/website/blog/2023-02-24-consistent-type-exports-and-imports-why-and-how.md
- 4: https://www.typescriptlang.org/docs/handbook/modules/reference
- 5:
import typeshould not need runtime modules support microsoft/TypeScript#44549 - 6: import type should not have any effect on output code microsoft/TypeScript#41562
- 7: https://exchangetuts.com/why-wont-typescript-let-me-import-a-type-from-an-es-module-into-a-commonjs-module-1768566602943785
Import useState as a runtime value.
useState is imported with import type, but the component calls it directly. Split the type import from the runtime import so useState is available at runtime.
Proposed fix
-import type { FormEvent, useState } from 'react';
+import { useState } from 'react';
+import type { FormEvent } from 'react';📝 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.
| import type { FormEvent, useState } from 'react'; | |
| import { useState } from 'react'; | |
| import type { FormEvent } from 'react'; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/components/PledgeForm.tsx` at line 1, Update the imports in
PledgeForm so useState is imported as a runtime value rather than through the
type-only import, while keeping FormEvent type-only. Ensure the component’s
direct useState call resolves at runtime.
| isSubmitting = false, | ||
| isPledgePending = false, | ||
| pledgeError = null, | ||
| acceptedTokens = [], |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Default token choices from the campaign.
When the optional acceptedTokens prop is omitted, multi-token campaigns render no selector and always pledge campaign.assetCode. Fall back to campaign.acceptedTokens before deriving the selected token and rendering options.
Proposed fix
- const selectedToken = token || campaign.assetCode;
+ const availableTokens = acceptedTokens.length > 0
+ ? acceptedTokens
+ : campaign.acceptedTokens;
+ const selectedToken = token || (
+ availableTokens.includes(campaign.assetCode)
+ ? campaign.assetCode
+ : availableTokens[0] ?? campaign.assetCode
+ );
...
- {acceptedTokens.length > 1 && (
+ {availableTokens.length > 1 && (
...
- {acceptedTokens.map((token) => (
+ {availableTokens.map((token) => (Also applies to: 36-36, 62-69
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/components/PledgeForm.tsx` at line 27, Update PledgeForm’s
acceptedTokens initialization to fall back to campaign.acceptedTokens when the
prop is omitted, then use that resolved list for selected-token derivation and
token-option rendering. Preserve campaign.assetCode behavior only when neither
source provides accepted tokens.
| {onClaim && ( | ||
| <button | ||
| className="btn-ghost" | ||
| type="button" | ||
| disabled={isSubmitting || !campaign.progress.canClaim || !connectedWallet || connectedWallet !== campaign.creator || !walletReady} | ||
| onClick={() => { void onClaim(campaign); }} | ||
| > | ||
| Claim vault | ||
| </button> | ||
| )} |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Handle rejected claim requests.
Line 87 discards onClaim’s promise. A failed claim becomes an unhandled rejection with no feedback; catch it and surface a claim error.
Proposed fix
- onClick={() => { void onClaim(campaign); }}
+ onClick={() => {
+ void onClaim(campaign).catch((error) => {
+ setSubmitError(error instanceof Error ? error.message : 'Claim failed');
+ });
+ }}📝 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.
| {onClaim && ( | |
| <button | |
| className="btn-ghost" | |
| type="button" | |
| disabled={isSubmitting || !campaign.progress.canClaim || !connectedWallet || connectedWallet !== campaign.creator || !walletReady} | |
| onClick={() => { void onClaim(campaign); }} | |
| > | |
| Claim vault | |
| </button> | |
| )} | |
| {onClaim && ( | |
| <button | |
| className="btn-ghost" | |
| type="button" | |
| disabled={isSubmitting || !campaign.progress.canClaim || !connectedWallet || connectedWallet !== campaign.creator || !walletReady} | |
| onClick={() => { | |
| void onClaim(campaign).catch((error) => { | |
| setSubmitError(error instanceof Error ? error.message : 'Claim failed'); | |
| }); | |
| }} | |
| > | |
| Claim vault | |
| </button> | |
| )} |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/components/PledgeForm.tsx` around lines 82 - 91, Update the
claim button handler in PledgeForm’s onClaim flow to await the returned promise
and catch rejected claim requests. Surface the caught error through the
component’s existing claim-error feedback mechanism, while preserving the
current campaign argument and button behavior.
| ], | ||
| "breaking-change-keywords": ["BREAKING CHANGE:"] |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
schema="$(mktemp)"
trap 'rm -f "$schema"' EXIT
curl -fsSL \
'https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json' \
> "$schema"
jq -e '.properties["breaking-change-keywords"]' "$schema" >/dev/nullRepository: ritik4ever/stellar-goal-vault
Length of output: 167
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf '--- release-please-config.json relevant lines ---\n'
cat -n release-please-config.json | sed -n '1,80p'
printf '\n--- release workflow action pins ---\n'
if [ -f .github/workflows/release.yml ]; then
cat -n .github/workflows/release.yml | sed -n '1,220p'
else
echo ".github/workflows/release.yml not found"
fi
printf '\n--- search for schema/config references ---\n'
rg -n '"breaking-change-keywords"|release-please|config-file|schema|additionalProperties|properties' .github release-please-config.json 2>/dev/null || trueRepository: ritik4ever/stellar-goal-vault
Length of output: 258
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
printf '%s\n' '--- release-please-config.json relevant lines ---'
cat -n release-please-config.json | sed -n '1,80p'
printf '%s\n' ''
printf '%s\n' '--- release workflow action pins ---'
if [ -f .github/workflows/release.yml ]; then
cat -n .github/workflows/release.yml | sed -n '1,220p'
else
echo ".github/workflows/release.yml not found"
fi
printf '%s\n' ''
printf '%s\n' '--- search for schema/config references ---'
rg -n '"breaking-change-keywords"|release-please|config-file|schema|additionalProperties|properties' .github release-please-config.json 2>/dev/null || true
printf '%s\n' ''
printf '%s\n' '--- all tracked release-please config files ---'
git ls-files '*release-please-config.json' '*release-please*' config.json 2>/dev/null || trueRepository: ritik4ever/stellar-goal-vault
Length of output: 5744
🌐 Web query:
google-github-actions release-please-action v4 breaking-change-keywords config-file schemas config.json
💡 Result:
The release-please-action v4 requires the use of a manifest-based configuration rather than many of the legacy action inputs [1][2]. Regarding "breaking-change-keywords," release-please follows the Conventional Commits specification by default [3][4]. According to this standard, breaking changes are indicated by appending an exclamation mark (!) to the type/scope (e.g., feat!: or fix!:) or by using a footer with "BREAKING CHANGE:" [5]. There is no explicit "breaking-change-keywords" configuration option in the current release-please-config.json schema [6]. Instead, the tool automatically detects breaking changes based on these standard Conventional Commit patterns [5]. Key details regarding v4 and configuration: 1. Migration to googleapis: Development has moved from google-github-actions/release-please-action to googleapis/release-please-action [5][7]. Users should update their workflows to use the new repository [5][3]. 2. Config File Schema: The official configuration is defined in release-please-config.json [6]. The schema for this file is maintained by the upstream release-please project [6]. You can validate your configuration against the official schema located at https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json [6][8]. 3. Configuration Format: In v4, most configuration is handled via a release-please-config.json file in your repository [3][9]. The action input config-file allows you to specify the path to this file (defaulting to release-please-config.json) [3][10]. 4. Inline Overrides: If you prefer not to use a separate configuration file for simple setups, you can use the config-overrides-json input to provide configuration options as a JSON string directly within your workflow file [9]. For advanced configuration, such as setting custom changelog sections or release types, refer to the official manifest-releaser documentation [3][11].
Citations:
- 1: https://github.com/googleapis/release-please-action/releases/tag/v4.0.0
- 2: https://github.com/googleapis/release-please-action/blob/main/CHANGELOG.md
- 3: https://github.com/googleapis/release-please-action
- 4: https://github.com/googleapis/release-please/blob/main/docs/customizing.md
- 5: https://pkg.go.dev/github.com/google-github-actions/release-please-action@v4.1.1+incompatible
- 6: https://catalog.lintel.tools/schemas/schemastore/release-please-config-json/
- 7: google-github-actions/release-please-action@google-github-actions:a37ac6e...google-github-actions:e4dc86b
- 8: https://github.com/google/dotprompt/blob/0911cf9e/.github/workflows/validate-release-please-config.yml
- 9: https://github.com/release-please-oss/release-please-action
- 10: https://github.com/marketplace/actions/release-please-action
- 11: https://github.com/googleapis/release-please/blob/main/docs/manifest-releaser.md
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
schema="$(mktemp)"
trap 'rm -f "$schema"' EXIT
curl -fsSL \
'https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json' \
> "$schema"
printf '%s\n' '--- top-level breaking-change-keywords property ---'
jq '.properties["breaking-change-keywords"]' "$schema"
printf '%s\n' ''
printf '%s\n' '--- property names containing breaking-change or changelog ---'
jq -r '.properties | to_entries[] | select(.key|test("break|change|changelog|packages|changelog-path"; "i")) | .key' "$schema"
printf '%s\n' ''
printf '%s\n' '--- package-level properties containing changelog/breaking/change ---'
jq -r '.properties.packages.type.description // empty, .properties.packages.properties | to_entries[] | select(.key|test("break|change|changelog|package-name"; "i")) | .key' "$schema"
printf '%s\n' ''
printf '%s\n' '--- schema additionalProperties settings ---'
jq -r '{top: .additionalProperties, packages: .properties.packages.properties."additionalProperties"}' "$schema"Repository: ritik4ever/stellar-goal-vault
Length of output: 527
Remove the unsupported breaking-change-keywords configuration.
release-please-config.json declares the official release-please schema, and that schema does not define breaking-change-keywords. Release Please follows Conventional Commits breaking-change handling (! in the header or BREAKING CHANGE: footer), so this custom entry is unnecessary and can make config validation fail or this option be ignored.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@release-please-config.json` around lines 31 - 32, Remove the unsupported
breaking-change-keywords property from the release-please configuration, leaving
the surrounding configuration and official schema-compatible options unchanged.
Source: MCP tools
|
Hi @DanbabaJr, This PR could not be merged because it has merge conflicts with the target branch. Please resolve the merge conflicts, push the updated changes, and the PR can be reviewed and merged. Thank you! |
1 similar comment
|
Hi @DanbabaJr, This PR could not be merged because it has merge conflicts with the target branch. Please resolve the merge conflicts, push the updated changes, and the PR can be reviewed and merged. Thank you! |
What Changed
This PR bundles three related frontend/docs improvements:
frontend/.storybook/, with stories covering all states forCampaignCard,PledgeForm,FundingProgress,Countdown,ContributorList, andToast. Documents design tokens and deploys the built Storybook to GitHub Pages.release-please-config.json, enforces Conventional Commits via commitlint, auto-generatesCHANGELOG.mdon release, adds a PR template with a commit-type selector, and flags breaking changes distinctly in release notes.Related Issues
Testing Done
npm run storybooklocally — confirmed it builds and runs without errors, and each story renders all documented component states with Tailwind styles applied correctly.feat:commit to a test branch and confirmedrelease-pleaseopened a release PR with an updatedCHANGELOG.md; verified aBREAKING CHANGE:footer was flagged distinctly in the generated notes.Security Review
(No API, auth, DB, or contract changes in this PR — checklist included for completeness.)
Checklist
npm test)Screenshots (if applicable)
Add screenshots/recording of: category filter sidebar + chips, Storybook component states, and a sample generated CHANGELOG entry.
Summary by CodeRabbit